From 6b9d1f4a61172369d5bbb679dc43c9e176105ee4 Mon Sep 17 00:00:00 2001 From: Clemens Barth Date: Fri, 8 Apr 2022 17:39:57 +0200 Subject: [PATCH] First committing --- AFM_thumbs.py | 3120 +++++++++++++++++ AFM_thumbs.pyc | Bin 0 -> 60290 bytes AFM_thumbs/Channel.py | 425 +++ AFM_thumbs/Channel.pyc | Bin 0 -> 8447 bytes AFM_thumbs/Colour.py | 145 + AFM_thumbs/Colour.pyc | Bin 0 -> 3022 bytes AFM_thumbs/Command_line.py | 308 ++ AFM_thumbs/Command_line.pyc | Bin 0 -> 7086 bytes AFM_thumbs/Config_AFM_thumbs.conf | 166 + AFM_thumbs/Config_AFM_thumbs.conf~ | 166 + AFM_thumbs/Config_default.conf | 177 + AFM_thumbs/Config_default.conf~ | 166 + AFM_thumbs/Initialize.py | 223 ++ AFM_thumbs/Initialize.pyc | Bin 0 -> 4965 bytes AFM_thumbs/Linalg.py | 251 ++ AFM_thumbs/Linalg.pyc | Bin 0 -> 5128 bytes AFM_thumbs/Nanotec_DULCINEA.py | 452 +++ AFM_thumbs/Nanotec_DULCINEA.pyc | Bin 0 -> 8901 bytes AFM_thumbs/Omicron_SCALA.py | 417 +++ AFM_thumbs/Omicron_SCALA.pyc | Bin 0 -> 9209 bytes AFM_thumbs/PDF.py | 267 ++ AFM_thumbs/PDF.pyc | Bin 0 -> 3497 bytes AFM_thumbs/RHK.py | 674 ++++ AFM_thumbs/RHK.pyc | Bin 0 -> 11732 bytes AFM_thumbs/SPECS_Nanonis.py | 947 +++++ AFM_thumbs/SPECS_Nanonis.pyc | Bin 0 -> 18843 bytes AFM_thumbs/SPECS_Nanonis.txt | 571 +++ AFM_thumbs/Thumbs.py | 463 +++ AFM_thumbs/Thumbs.pyc | Bin 0 -> 9510 bytes AFM_thumbs/ToolTip.py | 77 + AFM_thumbs/ToolTip.pyc | Bin 0 -> 2652 bytes AFM_thumbs/Variables.py | 648 ++++ AFM_thumbs/Variables.pyc | Bin 0 -> 18551 bytes AFM_thumbs/Variables.py~ | 568 +++ AFM_thumbs/__init__.py | 25 + AFM_thumbs/__init__.pyc | Bin 0 -> 154 bytes AFM_thumbs/__pycache__/Channel.cpython-36.pyc | Bin 0 -> 6876 bytes AFM_thumbs/__pycache__/Channel.cpython-38.pyc | Bin 0 -> 6701 bytes AFM_thumbs/__pycache__/Colour.cpython-36.pyc | Bin 0 -> 2655 bytes AFM_thumbs/__pycache__/Colour.cpython-38.pyc | Bin 0 -> 2487 bytes .../__pycache__/Command_line.cpython-36.pyc | Bin 0 -> 5911 bytes .../__pycache__/Command_line.cpython-38.pyc | Bin 0 -> 5668 bytes .../__pycache__/Initialize.cpython-36.pyc | Bin 0 -> 3960 bytes .../__pycache__/Initialize.cpython-38.pyc | Bin 0 -> 4170 bytes AFM_thumbs/__pycache__/Linalg.cpython-36.pyc | Bin 0 -> 4383 bytes AFM_thumbs/__pycache__/Linalg.cpython-38.pyc | Bin 0 -> 4493 bytes .../Nanotec_DULCINEA.cpython-36.pyc | Bin 0 -> 7052 bytes .../Nanotec_DULCINEA.cpython-38.pyc | Bin 0 -> 7061 bytes .../__pycache__/Omicron_SCALA.cpython-36.pyc | Bin 0 -> 7321 bytes .../__pycache__/Omicron_SCALA.cpython-38.pyc | Bin 0 -> 7347 bytes AFM_thumbs/__pycache__/PDF.cpython-36.pyc | Bin 0 -> 2768 bytes AFM_thumbs/__pycache__/PDF.cpython-38.pyc | Bin 0 -> 3005 bytes AFM_thumbs/__pycache__/RHK.cpython-36.pyc | Bin 0 -> 9759 bytes AFM_thumbs/__pycache__/RHK.cpython-38.pyc | Bin 0 -> 10117 bytes .../__pycache__/SPECS_Nanonis.cpython-36.pyc | Bin 0 -> 16230 bytes .../__pycache__/SPECS_Nanonis.cpython-38.pyc | Bin 0 -> 16052 bytes AFM_thumbs/__pycache__/Thumbs.cpython-36.pyc | Bin 0 -> 7427 bytes AFM_thumbs/__pycache__/Thumbs.cpython-38.pyc | Bin 0 -> 7497 bytes AFM_thumbs/__pycache__/ToolTip.cpython-36.pyc | Bin 0 -> 1942 bytes AFM_thumbs/__pycache__/ToolTip.cpython-38.pyc | Bin 0 -> 2021 bytes .../__pycache__/Variables.cpython-36.pyc | Bin 0 -> 14845 bytes .../__pycache__/Variables.cpython-38.pyc | Bin 0 -> 13774 bytes .../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 150 bytes .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 211 bytes AFM_thumbs_Icon.png | Bin 0 -> 3396 bytes Config_AFM_thumbs_noline.log | 48 + .../Linux/Ubuntu_unity/AFM_thumbs.desktop | 7 + Utilities/Windows/AFM_thumbs_icon.ico | Bin 0 -> 370070 bytes Utilities/Windows/AFM_thumbs_starter.lnk | Bin 0 -> 2243 bytes Utilities/Windows/Create_Windows_shortcut.bat | 35 + Utilities/Windows/Windows_batch_starter.bat | 3 + 71 files changed, 10349 insertions(+) create mode 100755 AFM_thumbs.py create mode 100755 AFM_thumbs.pyc create mode 100755 AFM_thumbs/Channel.py create mode 100755 AFM_thumbs/Channel.pyc create mode 100755 AFM_thumbs/Colour.py create mode 100755 AFM_thumbs/Colour.pyc create mode 100755 AFM_thumbs/Command_line.py create mode 100755 AFM_thumbs/Command_line.pyc create mode 100644 AFM_thumbs/Config_AFM_thumbs.conf create mode 100755 AFM_thumbs/Config_AFM_thumbs.conf~ create mode 100644 AFM_thumbs/Config_default.conf create mode 100755 AFM_thumbs/Config_default.conf~ create mode 100755 AFM_thumbs/Initialize.py create mode 100755 AFM_thumbs/Initialize.pyc create mode 100755 AFM_thumbs/Linalg.py create mode 100755 AFM_thumbs/Linalg.pyc create mode 100755 AFM_thumbs/Nanotec_DULCINEA.py create mode 100755 AFM_thumbs/Nanotec_DULCINEA.pyc create mode 100755 AFM_thumbs/Omicron_SCALA.py create mode 100755 AFM_thumbs/Omicron_SCALA.pyc create mode 100755 AFM_thumbs/PDF.py create mode 100755 AFM_thumbs/PDF.pyc create mode 100755 AFM_thumbs/RHK.py create mode 100755 AFM_thumbs/RHK.pyc create mode 100755 AFM_thumbs/SPECS_Nanonis.py create mode 100755 AFM_thumbs/SPECS_Nanonis.pyc create mode 100755 AFM_thumbs/SPECS_Nanonis.txt create mode 100755 AFM_thumbs/Thumbs.py create mode 100755 AFM_thumbs/Thumbs.pyc create mode 100755 AFM_thumbs/ToolTip.py create mode 100755 AFM_thumbs/ToolTip.pyc create mode 100755 AFM_thumbs/Variables.py create mode 100755 AFM_thumbs/Variables.pyc create mode 100755 AFM_thumbs/Variables.py~ create mode 100755 AFM_thumbs/__init__.py create mode 100755 AFM_thumbs/__init__.pyc create mode 100755 AFM_thumbs/__pycache__/Channel.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Channel.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Colour.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Colour.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Command_line.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Command_line.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Initialize.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Initialize.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Linalg.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Linalg.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Omicron_SCALA.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Omicron_SCALA.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/PDF.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/PDF.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/RHK.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/RHK.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Thumbs.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Thumbs.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/ToolTip.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/ToolTip.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/Variables.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/Variables.cpython-38.pyc create mode 100755 AFM_thumbs/__pycache__/__init__.cpython-36.pyc create mode 100644 AFM_thumbs/__pycache__/__init__.cpython-38.pyc create mode 100755 AFM_thumbs_Icon.png create mode 100755 Config_AFM_thumbs_noline.log create mode 100755 Utilities/Linux/Ubuntu_unity/AFM_thumbs.desktop create mode 100755 Utilities/Windows/AFM_thumbs_icon.ico create mode 100755 Utilities/Windows/AFM_thumbs_starter.lnk create mode 100755 Utilities/Windows/Create_Windows_shortcut.bat create mode 100755 Utilities/Windows/Windows_batch_starter.bat diff --git a/AFM_thumbs.py b/AFM_thumbs.py new file mode 100755 index 0000000..9927ba9 --- /dev/null +++ b/AFM_thumbs.py @@ -0,0 +1,3120 @@ +#!/usr/bin/env python +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# The python program AFM_thumbs creates a pdf file, which shows all SPM +# (Scanning Probe Microscopy: like AFM, STM, KPFM, etc.) images and relevant +# data stored in a directory. In first place, AFM_thumbs is interesting for +# scientists, who would like to obtain an overview of their SPM data. +# Supported SPM data: Omicron SCALA, Nanotec Dulicinea and RHK +# +# AFM_thumbs +# ========== +# +# Main author and project manager : Clemens Barth +# barth@root-1.de +# +# Main-author : Niklas Rethmann +# nrethmann@uni-osnabrueck.de +# +# +# Start of project : 2012/02/16, Clemens Barth +# Restructure of project : 2014/03/28, Clemens Barth +# Niklas Rethmann +# Transition to Python 3.x : 2022/02/17, Clemens Barth +# +# +# 2022/03/02 +# ========== +# - Bug removal in SPECS_Nanonis.py: do not prepare amplitude +# string if it is, e.g., a STM measurement. +# +# 2022/02/17 +# ========== +# - Transition to python 3.x +# +# 2022/01/28-29 +# ============= +# - The Nanonis spectroscopy (text info) has been entirely re-structured +# - Code for including Nanonis NPC and FCA spectroscopy curves +# - Code cleaning +# +# 2021/02/07 +# ========== +# - The code for adjusting the image contrast was considerably improved. +# In particular Nanonis images, which were not recorded until the end +# of the image frame, are better treated: the region of 'now data' is +# not considered. +# - Code cleaning +# +# 2021/02/06 +# ========== +# - Nanonis images with NaNs are now considered. The NaN values are all +# put onto zero. +# - Bug removal: if a directory contained only one Nanonis file, it was +# not considered. This has been solved. +# - All non-contact and KPFM channels in Nanonis files are now treated. +# - Code cleaning +# +# 2021/02/05 +# ========== +# - Bad fonts are excluded +# - Nanonis: the speed info now has a better format. +# +# 2021/01/21 +# ========== +# - First implementation of Nanonis .sxm files +# - Code cleaning +# +# 2018/09/12 +# ========== +# - If there is a bad font like 'NotoColorEmoji.ttf' then it will be +# not considered. +# +# 2017/07/28 +# ========== +# - All spectra of Omicron SCALA data are considered. +# - Spectra data always starts with a new row, the same for +# following images. DULCINEA has not yet spectra implemented. +# RHK: still needs to be done. +# +# 2017/06/25 +# ========== +# - 3 digits for Ugap +# - Console output: Change from 'Date' to 'Today' +# +# +# +# +# ##### BEGIN NOTE ##### +# +# This Python script is free for use. Me and others have put a huge effort +# into creating this nice program! +# PLEASE, if you modify this script, respect the following steps: +# +# 1. DO NOT REMOVE OUR NAMES FROM THE PREAMBLE AND KEEP ME AS A PROJECT MANAGER. +# 2. Send your new version by Email to: +# +# barth@root-1.de and +# +# 3. Keep the PEP-8 programming rules when coding: +# http://legacy.python.org/dev/peps/pep-0008/ +# +# Thank you! +# +# Dr. Clemens Barth, February 2022 +# +# ##### END NOTE ##### +# +# DO NOT REMOVE THIS PREAMBLE !!! + + + +from tkinter import * +import tkinter.filedialog as filedialog +import tkinter.messagebox as messagebox +import tkinter.ttk as ttk + + +import os +import platform +import matplotlib +from timeit import default_timer as timer +from datetime import datetime, timedelta + +from AFM_thumbs.Linalg import initialize_linalg +from AFM_thumbs.Variables import globvar_configfile +from AFM_thumbs.Variables import globvar_configfile_path +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_spaces +from AFM_thumbs.Variables import globvar_timepassed_1 +from AFM_thumbs.Variables import globvar_timepassed_2 +from AFM_thumbs.Variables import globvar_console +from AFM_thumbs.Variables import globvar_bar_title +from AFM_thumbs.Variables import globvar_name +from AFM_thumbs.Variables import globvar_note +from AFM_thumbs.Variables import globvar_thumb_size_x +from AFM_thumbs.Variables import globvar_thumb_size_y +from AFM_thumbs.Variables import TT_n_col +from AFM_thumbs.Variables import TT_n_row +from AFM_thumbs.Variables import TT_rms +from AFM_thumbs.Variables import TT_res +from AFM_thumbs.Variables import TT_qual +from AFM_thumbs.Variables import TT_size +from AFM_thumbs.Variables import TT_dx_pos +from AFM_thumbs.Variables import TT_dy_pos +from AFM_thumbs.Variables import TT_dw +from AFM_thumbs.Variables import TT_file_ex +from AFM_thumbs.Variables import TT_master_dir +from AFM_thumbs.Variables import TT_filename +from AFM_thumbs.Variables import TT_date +from AFM_thumbs.Variables import TT_size_nm +from AFM_thumbs.Variables import TT_size_px +from AFM_thumbs.Variables import TT_off +from AFM_thumbs.Variables import TT_vol +from AFM_thumbs.Variables import TT_feed +from AFM_thumbs.Variables import TT_loop +from AFM_thumbs.Variables import TT_speed +from AFM_thumbs.Variables import TT_amp +from AFM_thumbs.Variables import TT_angle +from AFM_thumbs.Variables import TT_thumb_before +from AFM_thumbs.Variables import TT_thumb_after +from AFM_thumbs.Variables import TT_extra_dir +from AFM_thumbs.Variables import TT_pdfs +from AFM_thumbs.Variables import TT_subdirs +from AFM_thumbs.Variables import TT_png +from AFM_thumbs.Variables import TT_spektral +from AFM_thumbs.Variables import TT_peek +from AFM_thumbs.Variables import TT_minimum_on_zero +from AFM_thumbs.Variables import SPECS_Nanonis_images_must_exist +from AFM_thumbs.Variables import SPECS_Nanonis_spectroscopy_must_exist +from AFM_thumbs.Variables import Nanotec_DULCINEA_must_exist +from AFM_thumbs.Variables import Omicron_SCALA_must_exist +from AFM_thumbs.Variables import RHK_must_exist +from AFM_thumbs.Variables import globvar_color_options +from AFM_thumbs.Variables import globvar_ttk_Combobox +from AFM_thumbs.Variables import globvar_fonts +from AFM_thumbs.Variables import globvar_bad_fonts +from AFM_thumbs.ToolTip import create_tool_tip +from AFM_thumbs.Channel import define_color +from AFM_thumbs.PDF import prepare_PDFs +from AFM_thumbs.Initialize import initialize_dir +from AFM_thumbs.Initialize import initialize_position_counter +from AFM_thumbs.Initialize import initialize_check_config +from AFM_thumbs.SPECS_Nanonis import is_SPECS_Nanonis_file +from AFM_thumbs.SPECS_Nanonis import read_SPECS_Nanonis_image_data +from AFM_thumbs.SPECS_Nanonis import prepare_SPECS_Nanonis_images +from AFM_thumbs.SPECS_Nanonis import prepare_SPECS_Nanonis_spectra_curves +from AFM_thumbs.Omicron_SCALA import is_omicron_SCALA_file +from AFM_thumbs.Omicron_SCALA import read_Omicron_SCALA_data +from AFM_thumbs.Omicron_SCALA import prepare_Omicron_SCALA_images +from AFM_thumbs.Omicron_SCALA import prepare_Omicron_SCALA_spectra_curves +from AFM_thumbs.Nanotec_DULCINEA import is_Nanotec_DULCINEA_file +from AFM_thumbs.Nanotec_DULCINEA import prepare_Nanotec_DULCINEA_images +from AFM_thumbs.RHK import is_RHK_file +from AFM_thumbs.RHK import read_RHK_data +from AFM_thumbs.Command_line import command_line +from AFM_thumbs.Colour import plot_color_gradients + + +# This is the definition, where the calculation starts. The respective Python +# modules of the SPM file formats are called for each image, which is indeed an +# SPM image. +def start_with_calculations(): + + if not initialize_dir(): + return False + +# __________________________ SPECS Nanonis + + # Find all SPECS Nanonis spectroscopy files in the directory + files = filter(lambda x: x.endswith(SPECS_Nanonis_spectroscopy_must_exist), + os.listdir(globvar_AFMdir.working_directory)) + files = sorted(files) + + if files != []: + print(globvar_spaces + + " ... SPECS Nanonis spectras are stored as thumbs ...") + for AFMfile in files: + if not AFMfile[0] == ".": + if globvar_ThumbPara.filename != "": + if re.search(globvar_ThumbPara.filename, AFMfile): + prepare_SPECS_Nanonis_spectra_curves(AFMfile) + else: + prepare_SPECS_Nanonis_spectra_curves(AFMfile) + + + # Find all SPECS Nanonis image files in the directory + files = filter(lambda x: x.endswith(SPECS_Nanonis_images_must_exist), + os.listdir(globvar_AFMdir.working_directory)) + files = sorted(files) + + if files != []: + print(globvar_spaces + + " ... SPECS Nanonis images are stored as thumbs ...") + for AFMfile in files: + if not AFMfile[0] == ".": + if globvar_ThumbPara.filename != "": + if re.search(globvar_ThumbPara.filename, AFMfile): + data_offset = read_SPECS_Nanonis_image_data(AFMfile) + prepare_SPECS_Nanonis_images(AFMfile, data_offset) + else: + data_offset = read_SPECS_Nanonis_image_data(AFMfile) + prepare_SPECS_Nanonis_images(AFMfile, data_offset) + + + +# __________________________ Omicron SCALA + + # Find all .par files in the directory + files = filter(lambda x: x.endswith(Omicron_SCALA_must_exist), + os.listdir(globvar_AFMdir.working_directory)) + files = sorted(files) + + if files != []: + if globvar_ThumbPara.spektra == 1: + print(globvar_spaces + + " ... Omicron SCALA spectra are stored as thumbs ...") + for AFMfile in files: + if not AFMfile[0] == ".": + if globvar_ThumbPara.filename != "": + if re.search(globvar_ThumbPara.filename, AFMfile): + read_Omicron_SCALA_data(AFMfile) + prepare_Omicron_SCALA_spectra_curves(AFMfile) + else: + read_Omicron_SCALA_data(AFMfile) + prepare_Omicron_SCALA_spectra_curves(AFMfile) + + if files != []: + print(globvar_spaces + + " ... Omicron SCALA images are stored as thumbs ...") + for AFMfile in files: + if not AFMfile[0] == ".": + if globvar_ThumbPara.filename != "": + if re.search(globvar_ThumbPara.filename, AFMfile): + read_Omicron_SCALA_data(AFMfile) + prepare_Omicron_SCALA_images(AFMfile) + else: + read_Omicron_SCALA_data(AFMfile) + prepare_Omicron_SCALA_images(AFMfile) + +# __________________________ Nanotec DULCINEA + + # Find all .f.top files in the directory + files = filter(lambda x: x.endswith(Nanotec_DULCINEA_must_exist), + os.listdir(globvar_AFMdir.working_directory)) + files = sorted(files) + + if files != []: + print(globvar_spaces + + " ... Nanotec DULCINEA images are stored as thumbs ...") + for AFMfile in files: + if not AFMfile[0] == ".": + if globvar_ThumbPara.filename != "": + if re.search(globvar_ThumbPara.filename,AFMfile): + prepare_Nanotec_DULCINEA_images(AFMfile) + else: + prepare_Nanotec_DULCINEA_images(AFMfile) + + +# __________________________ RHK + + # Find all .SM4 and .sm4 files in the directory + files_1 = filter(lambda x: x.endswith(RHK_must_exist[0]), + os.listdir(globvar_AFMdir.working_directory)) + + # To be verified if it works, C. Barth 2022-02-17 + files_2 = filter(lambda x: x.endswith(RHK_must_exist[1]), + os.listdir(globvar_AFMdir.working_directory)) + files = sorted(list(files_1) + list(files_2)) + + if files != []: + initialize_position_counter() + + # Note that the creation of the thumbnails for spectra is done inside + # read_RHK_data! + print(globvar_spaces + " ... RHK images and are stored as thumbs ...") + for AFMfile in files: + if not AFMfile[0] == ".": + if globvar_ThumbPara.filename != "": + if re.search(globvar_ThumbPara.filename,AFMfile): + read_RHK_data(AFMfile) + else: + read_RHK_data(AFMfile) +# __________________________ Prepare pdfs + + print(globvar_spaces + " ... pdfs are built ...") + print + + prepare_PDFs() + + return True + +# ____________________________________________________ Start calculating images + + +# This is basically the definition, where the images are searched in the +# working directory. The definition 'start_with_calculations()' (see above) is +# then called. +def initialize_and_go(directory_start, config_file): + + # Here the last note for the AFM_thumbs header that is shown in the console. + # The config file will be printed. + if config_file is not None: + config_file_path = config_file + else: + config_file_path = os.path.join(globvar_configfile_path, + globvar_configfile) + print(globvar_spaces + + "Config file: " + + config_file_path + + "\n\n") + + list_tmp = [] + initialize_linalg() + + # Recursive directory search ... all subdirectories shall be considered. + # Option 'All-subdirectories' activated + if globvar_ThumbPara.subdirs == 1: + + for directory, dirnames, filenames in os.walk(directory_start): + # Take only data, that is in a 'main' directory called, e.g., + # 'sample'. + if globvar_ThumbPara.masterdir != "": + if globvar_ThumbPara.masterdir not in directory: + continue + + # Are there Omicron, Nanotec, ... files? + list_tmp += is_SPECS_Nanonis_file(directory, filenames) + list_tmp += is_omicron_SCALA_file(directory, filenames) + list_tmp += is_Nanotec_DULCINEA_file(directory, filenames) + list_tmp += is_RHK_file(directory, filenames) + + # Sort the directory list + list_directories = sorted(list_tmp) + + print(globvar_spaces + "Directories that will be considered:") + for directory in list_directories: + print(globvar_spaces + directory) + print("\n\n") + for directory in list_directories: + print(globvar_spaces + " I'm working in the directory\n" + + globvar_spaces + " " + directory + "\n" + + globvar_spaces + " right now ...\n") + globvar_AFMdir.working_directory = directory + start_with_calculations() + + # Only one directory is considered. Option 'All-subdirectories' is + # deactivated. + else: + globvar_AFMdir.working_directory = directory_start + list_dir = os.listdir(globvar_AFMdir.working_directory) + + list_tmp = [] + list_tmp += is_SPECS_Nanonis_file(directory, filenames) + list_tmp += is_omicron_SCALA_file(directory_start, list_dir) + list_tmp += is_Nanotec_DULCINEA_file(directory_start, list_dir) + list_tmp += is_RHK_file(directory_start, list_dir) + + # Finally: the routine is called + if list_tmp != []: + start_with_calculations() + + +# _____________________________________________________________ Tkinter Windows + + +class MyDialog(Frame): + + def __init__(self, master): + + ''' + Initialisation Method + ''' + + self.op_sys = platform.system() + self.working_directory = "" + self.pdf_path = "" + self.filepath_config = initialize_check_config(None) + self.mainWindow = Frame(master) + Frame.__init__(self,master) + self.master.title(globvar_bar_title) + self.createWidgets() + + def createWidgets(self): + + ''' + Method for creating all GUI specific components + ''' + + master = self.master + + # Extra Frame for the following frames so it will not shift + # the formating + self.frameLeft = Frame(self.master) + self.frameLeft.grid(row=1, column=0, columnspan=6, sticky=W+E+N+S) + + # Arangement of images + + Label(self.frameLeft, text=" ").grid(row=0, sticky=W) + Label(self.frameLeft, + text="Arrangement of images", + fg="blue").grid(row=1, sticky=W) + + Label(self.frameLeft, + text="No. of images in column").grid(row=2, column=0, sticky=W) + self.n_col = Entry(self.frameLeft, width=3) + self.n_col.delete(0, END) + self.n_col.grid(row=2, column=1) + self.n_col.bind("", self.lost_focus) + + Label(self.frameLeft, + text="No. of images in row").grid(row=3, column=0, sticky=W) + self.n_row = Entry(self.frameLeft, width=3) + self.n_row.delete(0, END) + self.n_row.grid(row=3, column=1) + self.n_row.bind("", self.lost_focus) + + Label(self.frameLeft, + text="Contrast").grid(row=4, column=0, sticky=W) + self.rms = Entry(self.frameLeft, width=3) + self.rms.delete(0, END) + self.rms.grid(row=4, column=1) + self.rms.bind("", self.lost_focus) + + Label(self.frameLeft, + text="Image resolution").grid(row=5, column=0, sticky=W) + self.res = Entry(self.frameLeft, width=3) + self.res.delete(0, END) + self.res.grid(row=5, column=1) + self.res.bind("", self.lost_focus) + + Label(self.frameLeft, + text="Image quality").grid(row=6, column=0, sticky=W) + self.jpeg = Entry(self.frameLeft, width=3) + self.jpeg.delete(0, END) + self.jpeg.grid(row=6, column=1) + self.jpeg.bind("", self.lost_focus) + + # Position/size of body text + + Label(self.frameLeft, + text=" ").grid(row=8, sticky=W) + + Label(self.frameLeft, + text="Position/size of body text", + fg="blue").grid(row=8, column=0, sticky=W) + + Label(self.frameLeft, + text="Font size").grid(row=9, column=0, sticky=W) + self.text_size = Entry(self.frameLeft, width=4) + self.text_size.delete(0, END) + self.text_size.grid(row=9, column=1) + self.text_size.bind("", self.lost_focus) + + Label(self.frameLeft, + text="dX position").grid(row=10, column=0, sticky=W) + self.text_x = Entry(self.frameLeft, width=4) + self.text_x.delete(0, END) + self.text_x.grid(row=10, column=1) + self.text_x.bind("", self.lost_focus) + + Label(self.frameLeft, + text="dY position").grid(row=11, column=0, sticky=W) + self.text_y = Entry(self.frameLeft, width=4) + self.text_y.delete(0, END) + self.text_y.grid(row=11, column=1) + self.text_y.bind("", self.lost_focus) + + Label(self.frameLeft, + text="dWidth of text").grid(row=12, column=0, sticky=W) + self.text_block = Entry(self.frameLeft, width=4) + self.text_block.delete(0, END) + self.text_block.grid(row=12, column=1) + self.text_block.bind("", self.lost_focus) + + # Select font + Label(self.frameLeft, + text="Select font").grid(row=14, column=0, sticky=W) + self.fonts = self.get_fonts() + self.font_menu_var = StringVar() + self.font_menu = ttk.Combobox(self.frameLeft, + textvariable=self.font_menu_var, + values=self.fonts, + width = globvar_ttk_Combobox, + state='readonly') + self.font_menu.grid(row=14, column=1, sticky=W) + self.font_menu.current(0) # set selection + self.font_menu.bind("<>", self.lost_focus) + + # File Options + + Label(self.frameLeft, + text="File suffix").grid(row=16, column=0, sticky=W) + self.extension = Entry(self.frameLeft, width=10) + self.extension.delete(0, END) + self.extension.grid(row=16, column=1) + self.extension.bind("", self.lost_focus) + + Label(self.frameLeft, + text="Path contains").grid(row=17, column=0, sticky=W) + self.masterdir = Entry(self.frameLeft, width=10) + self.masterdir.delete(0, END) + self.masterdir.grid(row=17, column=1) + self.masterdir.bind("", self.lost_focus) + + Label(self.frameLeft, + text="File name contains").grid(row=18, column=0, sticky=W) + self.filename = Entry(self.frameLeft, width=10) + self.filename.delete(0, END) + self.filename.grid(row=18, column=1) + self.filename.bind("", self.lost_focus) + + Label(self.frameLeft, text=" ").grid(column=2, sticky=W) + + # Parameters of measurements + + Label(self.frameLeft, + text=" Parameters of measurements", + fg="blue").grid(row=1, column=3, columnspan=2, sticky=W) + + self.date_var = IntVar() + self.date = Checkbutton(self.frameLeft, + text=" Date and time", + variable=self.date_var) + self.date.grid(row=2, column=3, sticky=W) + + self.sizenm_var = IntVar() + self.sizenm = Checkbutton(self.frameLeft, + text=" Size (nm)", + variable=self.sizenm_var) + self.sizenm.grid(row=3, column=3, sticky=W) + + self.sizepx_var = IntVar() + self.sizepx = Checkbutton(self.frameLeft, + text=" Size (pixel)", + variable=self.sizepx_var) + self.sizepx.grid(row=4, column=3, sticky=W) + + self.offset_var = IntVar() + self.offset = Checkbutton(self.frameLeft, + text=" Offset", + variable=self.offset_var) + self.offset.grid(row=5, column=3, sticky=W) + + self.voltage_var = IntVar() + self.voltage = Checkbutton(self.frameLeft, + text=" Voltage", + variable=self.voltage_var) + self.voltage.grid(row=6, column=3, sticky=W) + + self.feedback_var = IntVar() + self.feedback = Checkbutton(self.frameLeft, + text=" Feedback", + variable=self.feedback_var) + self.feedback.grid(row=2, column=4, sticky=W) + + self.gain_var = IntVar() + self.gain = Checkbutton(self.frameLeft, + text=" Loop gain", + variable=self.gain_var) + self.gain.grid(row=3, column=4, sticky=W) + + self.speed_var = IntVar() + self.speed = Checkbutton(self.frameLeft, + text=" Speed", + variable=self.speed_var) + self.speed.grid(row=4, column=4, sticky=W) + + self.ampl_var = IntVar() + self.ampl = Checkbutton(self.frameLeft, + text=" Amplitude ", + variable=self.ampl_var) + self.ampl.grid(row=5, column=4, sticky=W) + + self.angle_var = IntVar() + self.angle = Checkbutton(self.frameLeft, + text=" Angle ", + variable=self.angle_var) + self.angle.grid(row=6, column=4, sticky=W) + + # Other options + + Label(self.frameLeft, + text=" Other options", fg="blue").grid(row=8,column=3,sticky=W) + + self.thumbs_before_var = IntVar() + self.thumbs_before = Checkbutton(self.frameLeft, + text=" Delete before", + variable=self.thumbs_before_var) + self.thumbs_before.grid(row=9, column=3, sticky=W) + + self.thumbs_after_var = IntVar() + self.thumbs_after = Checkbutton(self.frameLeft, + text=" Delete after", + variable=self.thumbs_after_var) + self.thumbs_after.grid(row=10, column=3, sticky=W) + + self.extra_directories_var = IntVar() + self.extra_directories = Checkbutton(self.frameLeft, + text=" Extra dir", + variable= \ + self.extra_directories_var) + self.extra_directories.grid(row=11, column=3, sticky=W) + + self.pdfs_var = IntVar() + self.pdfs = Checkbutton(self.frameLeft, + text=" Replace pdfs", + variable=self.pdfs_var) + self.pdfs.grid(row=12, column=3, sticky=W) + + self.subdirs_var = IntVar() + self.subdirs = Checkbutton(self.frameLeft, + text=" All sub dirs", + variable=self.subdirs_var) + self.subdirs.grid(row=13, column=3, sticky=W) + + self.format_var = IntVar() + self.format = Checkbutton(self.frameLeft, + text=" PNG/JPEG", + variable=self.format_var) + self.format.grid(row=9, column=4, sticky=W) + + self.skala_var = IntVar() + self.skala = Checkbutton(self.frameLeft, + text=" Spectro", + variable=self.skala_var) + self.skala.grid(row=10, column=4, sticky=W) + + self.peek_var = IntVar() + self.peek = Checkbutton(self.frameLeft, + text=" Peak-peak", + variable=self.peek_var) + self.peek.grid(row=11, column=4, sticky=W) + + self.minimum_on_zero_var = IntVar() + self.minimum_on_zero = Checkbutton(self.frameLeft, + text=" Min on 0", + variable=self.minimum_on_zero_var) + self.minimum_on_zero.grid(row=12, column=4, sticky=W) + + # Hide Tooltips + + Label(self.frameLeft, text=" ").grid(column=5, sticky=W) + + + Label(self.frameLeft, + text="Hide Tool-tips", fg="blue").grid(row=16, + column=3, + sticky=W) + + self.tooltip_var = IntVar() + + self.show_tipps = Radiobutton(self.frameLeft, + text="Show", + variable=self.tooltip_var, + value=0, command=self.sh_tooltips) + self.show_tipps.grid(row=17, column=3, sticky=W) + + self.hide_tipps = Radiobutton(self.frameLeft, + text="Hide", + variable=self.tooltip_var, + value=1, + command=self.no_tooltips) + self.hide_tipps.grid(row=17, column=4, sticky=W) + + # Select Radiobuttons + + Label(self.frameLeft, + text="Select thumbs", fg="blue").grid(row=1, + column=6, + sticky=W) + + self.thumbs_var = IntVar() + + self.thumbs_all = Radiobutton(self.frameLeft, + text="All", + variable=self.thumbs_var, + value=0, + command=self.select_thumbs_all) + self.thumbs_all.grid(row=2, column=6, sticky=W) + + self.thumbs_for = Radiobutton(self.frameLeft, + text="Forward", + variable=self.thumbs_var, + value=1, + command=self.select_thumbs_for) + self.thumbs_for.grid(row=3, column=6, sticky=W) + + self.thumbs_back = Radiobutton(self.frameLeft, + text="Backward", + variable=self.thumbs_var, + value=2, + command=self.select_thumbs_back) + self.thumbs_back.grid(row=4, column=6, sticky=W) + + self.thumbs_none = Radiobutton(self.frameLeft, + text="None", + variable=self.thumbs_var, + value=3, + command=self.select_thumbs_none) + self.thumbs_none.grid(row=5, column=6, sticky=W) + + + Label(self.frameLeft, + text="Select line fit", + fg="blue").grid(row=6, column=6, sticky=W) + + self.lin_var = IntVar() + + self.lin_all = Radiobutton(self.frameLeft, + text="All", + variable=self.lin_var, + value=0, + command=self.select_lin_all) + self.lin_all.grid(row=7, column=6, sticky=W) + + self.lin_for = Radiobutton(self.frameLeft, + text="Forward", + variable=self.lin_var, + value=1, + command=self.select_lin_for) + self.lin_for.grid(row=8, column=6, sticky=W) + + self.lin_back = Radiobutton(self.frameLeft, + text="Backward", + variable=self.lin_var, + value=2, + command=self.select_lin_back) + self.lin_back.grid(row=9, column=6, sticky=W) + + self.lin_none = Radiobutton(self.frameLeft, + text="None", + variable=self.lin_var, + value=3, + command=self.select_lin_none) + self.lin_none.grid(row=10, column=6, sticky=W) + + Label(self.frameLeft, + text="Select plane fit", + fg="blue").grid(row=11, column=6, sticky=W) + + self.plane_var = IntVar() + + self.plane_all = Radiobutton(self.frameLeft, + text="All", + variable=self.plane_var, + value=0, + command=self.select_plane_all) + self.plane_all.grid(row=12, column=6, sticky=W) + + self.plane_for = Radiobutton(self.frameLeft, + text="Forward", + variable=self.plane_var, + value=1, + command=self.select_plane_for) + self.plane_for.grid(row=13, column=6, sticky=W) + + self.plane_back = Radiobutton(self.frameLeft, + text="Backward", + variable=self.plane_var, + value=2, + command=self.select_plane_back) + self.plane_back.grid(row=14, column=6, sticky=W) + + self.plane_none = Radiobutton(self.frameLeft, + text="None", + variable=self.plane_var, + value=3, + command=self.select_plane_none) + self.plane_none.grid(row=15, column=6, sticky=W) + + + Label(self.frameLeft, + text="Select inversion", + fg="blue").grid(row=16, column=6, sticky=W) + + self.invert_var = IntVar() + + self.invert_all = Radiobutton(self.frameLeft, + text="All", + variable=self.invert_var, + value=0, + command=self.select_invert_all) + self.invert_all.grid(row=17, column=6, sticky=W) + + self.invert_for = Radiobutton(self.frameLeft, + text="Forward", + variable=self.invert_var, + value=1, + command=self.select_invert_for) + self.invert_for.grid(row=18, column=6, sticky=W) + + self.invert_back = Radiobutton(self.frameLeft, + text="Backward", + variable=self.invert_var, + value=2, + command=self.select_invert_back) + self.invert_back.grid(row=19, column=6, sticky=W) + + self.invert_none = Radiobutton(self.frameLeft, + text="None", + variable=self.invert_var, + value=3, + command=self.select_invert_none) + self.invert_none.grid(row=20, column=6, sticky=W) + + Label(self.frameLeft, + text="", width=5).grid(column=7, sticky=W) + + # Channel Options + + # Extra Frame for the following frames so it will not shift + # the formating. + self.frameUber = Frame(self.master) + self.frameUber.grid(row=1, column=7, columnspan=6, sticky=W+E+N+S) + + # Frame for Channel List + self.frameOne = Frame(self.frameUber) + self.frameOne.grid(row=0, column=0, sticky=W+E+N+S) + Label(self.frameOne, text=" ").grid(row=0, sticky=W) + + # List for saving the references of all Var-Objects + self.name_list = [] + self.thumb_list = [] + self.linefit_list = [] + self.planefit_list = [] + self.invert_list = [] + self.color_list = [] + + # Set Width of columns + Label(self.frameOne, text="", width=12).grid(row=1, + column=0, + sticky=W) + Label(self.frameOne, text="", width=8).grid(row=1, + column=1, + sticky=W) + Label(self.frameOne, text="", width=8).grid(row=1, + column=2, + sticky=W) + Label(self.frameOne, text="", width=8).grid(row=1, + column=3, + sticky=W) + Label(self.frameOne, text="", width=6).grid(row=1, + column=4, + sticky=W) + + # Captions, labels and direction arrows in frameOne + Label(self.frameOne, text="Channel", fg="blue").grid(row=1, + column=0, + sticky=W) + + Label(self.frameOne, text="Topography").grid(row=2, column=0, sticky=W) + Label(self.frameOne, text="Topography").grid(row=3, column=0, sticky=W) + Label(self.frameOne, text="df").grid(row=4, column=0, sticky=W) + Label(self.frameOne, text="df").grid(row=5, column=0, sticky=W) + Label(self.frameOne, text="Dissipation").grid(row=7, column=0,sticky=W) + Label(self.frameOne, text="Dissipation").grid(row=8, column=0,sticky=W) + Label(self.frameOne, text="Amplitude").grid(row=9, column=0, sticky=W) + Label(self.frameOne, text="Amplitude").grid(row=10, column=0, sticky=W) + + self.name_list.append("Topography") + self.name_list.append("df") + self.name_list.append("Dissipation") + self.name_list.append("Amplitude") + + Label(self.frameOne, text="", width=10).grid(row=1, column=1, sticky=W) + Label(self.frameOne, text="Direction", fg="blue").grid(row=1, + column=1, + sticky=W+S) + + Label(self.frameOne, text=" --->").grid(row=2, column=1, sticky=W+S) + Label(self.frameOne, text=" <---").grid(row=3, column=1, sticky=W) + Label(self.frameOne, text=" --->").grid(row=4, column=1, sticky=W) + Label(self.frameOne, text=" <---").grid(row=5, column=1, sticky=W) + Label(self.frameOne, text=" --->").grid(row=7, column=1, sticky=W) + Label(self.frameOne, text=" <---").grid(row=8, column=1, sticky=W) + Label(self.frameOne, text=" --->").grid(row=9, column=1, sticky=W) + Label(self.frameOne, text=" <---").grid(row=10, column=1, sticky=W) + + Label(self.frameOne, text="", width=10).grid(row=1, + column=2, + sticky=W) + Label(self.frameOne, text="Thumb", fg="blue").grid(row=1, + column=2, + sticky=W+S) + + Label(self.frameOne, text="", width=10).grid(row=1, column=3, sticky=W) + Label(self.frameOne, text="Line fit", fg="blue").grid(row=1, + column=3, + sticky=W+S) + + Label(self.frameOne, text="", width=10).grid(row=1, + column=4, + sticky=W) + Label(self.frameOne, text="Plane fit", fg="blue").grid(row=1, + column=4, + sticky=W+S) + + Label(self.frameOne, text="", width=10).grid(row=1, + column=5, + sticky=W) + Label(self.frameOne, text="Inversion", fg="blue").grid(row=1, + column=5, + sticky=W+S) + + Label(self.frameOne, text="", width=6).grid(row=1, + column=6, + sticky=W) + Label(self.frameOne, text="Color map", fg="blue").grid(row=1, + column=6, + sticky=W+S) + + # Loop for creating the Checkboxs and the Color Options in frameOne + + # Variables for loop + self.rowcounter = 2 + self.addspace = 0 + + while self.rowcounter < 11: + + self.thumbs_temp_var = IntVar() + self.thumbs_temp = Checkbutton(self.frameOne, + text="", + variable=self.thumbs_temp_var, + command=self.deselect_met) + + self.thumbs_temp.grid(row=self.rowcounter, column=2, sticky=W) + self.thumb_list.append(self.thumbs_temp_var) + + self.line_fit_temp_var = IntVar() + self.line_fit_temp = Checkbutton(self.frameOne, + text="", + variable=self.line_fit_temp_var, + command=self.select_met) + + self.line_fit_temp.grid(row=self.rowcounter, column=3, sticky=W) + + self.linefit_list.append(self.line_fit_temp_var) + + self.plane_fit_temp_var = IntVar() + self.plane_fit_temp = Checkbutton(self.frameOne, + text="", + variable=self.plane_fit_temp_var, + command=self.select_met) + + self.plane_fit_temp.grid(row=self.rowcounter, column=4, sticky=W) + + self.planefit_list.append(self.plane_fit_temp_var) + + self.invert_temp_var = IntVar() + self.invert_temp = Checkbutton(self.frameOne, + text="", + variable=self.invert_temp_var, + command=self.select_met) + + self.invert_temp.grid(row=self.rowcounter, column=5, sticky=W) + + self.invert_list.append(self.invert_temp_var) + + self.color_menu_var = StringVar() + self.color_menu = ttk.Combobox(self.frameOne, + textvariable=self.color_menu_var, + values=globvar_color_options, + width = globvar_ttk_Combobox, + state='readonly') + self.color_menu.grid(row=self.rowcounter, + column=6, + sticky=W) + self.color_menu.current(0) + self.color_menu.bind("<>", self.lost_focus) + + self.color_list.append(self.color_menu_var) + + self.rowcounter += 1 + self.addspace += 1 + + if self.addspace == 4: + self.addspace = 0 + Label(self.frameOne, text=" ").grid(row=self.rowcounter, + sticky=W) + self.rowcounter += 1 + + self.frameTwo = Frame(self.frameUber) + self.frameTwo.grid(row=2, column=0, sticky=W) + + # Creation of a new frame, inside of "frameTwo" for new fields + # Creation of a scrollbar + + # The reason for this is to attach the scrollbar to "FrameTwo", and + # when the size of frame "ListFrame" exceeds the size of frameTwo, + # the scrollbar acts. + self.canvas=Canvas(self.frameTwo) + self.listFrame=Frame(self.canvas) + self.scrollb=Scrollbar(self.frameUber, orient="vertical", + command=self.canvas.yview) + # The grid scrollbar is in self.frameUber, but ... + self.scrollb.grid(row=2, column=1, sticky='nsew') + # ... attach the scrollbar to frameTwo. + self.canvas['yscrollcommand'] = self.scrollb.set + + # + self.canvas.create_window((0,0),window=self.listFrame,anchor='nw') + self.listFrame.bind("", self.AuxscrollFunction) + # Forget the scrollbar because the number of pieces remains undefined + # by the user. But do not destroy it. It will be "remembered" later. + self.scrollb.grid_forget() + + self.canvas.pack(side="left") + self.frameThree = Frame(self.frameUber) + self.frameThree.grid(row=3, column=0) + + self.AuxscrollFunction(event=None) + + # Mousewheel binding + self.frameTwo.bind('', self.activate_mousewheel) + self.frameTwo.bind('', self.deactivate_mousewheel) + + # Set Width of columns + + Label(self.listFrame, text="", width=12).grid(row=1, + column=0, + sticky=W) + Label(self.listFrame, text="", width=10).grid(row=1, + column=1, + sticky=W) + Label(self.listFrame, text="", width=10).grid(row=1, + column=2, + sticky=W) + Label(self.listFrame, text="", width=10).grid(row=1, + column=3, + sticky=W) + Label(self.listFrame, text="", width=10).grid(row=1, + column=4, + sticky=W) + Label(self.listFrame, text="", width=10).grid(row=1, + column=5, + sticky=W) + Label(self.listFrame, text="", width=6).grid(row=1, + column=6, + sticky=W) + + Label(self.listFrame, text="Kelvin").grid(row=0, + column=0, + sticky=W) + Label(self.listFrame, text="Kelvin").grid(row=1, + column=0, + sticky=W) + Label(self.listFrame, text="Kelvin Error").grid(row=2, + column=0, + sticky=W) + Label(self.listFrame, text="Kelvin Error").grid(row=3, + column=0, + sticky=W) + Label(self.listFrame, text="Ext 1").grid(row=5, + column=0, + sticky=W) + Label(self.listFrame, text="Ext 1").grid(row=6, + column=0, + sticky=W) + Label(self.listFrame, text="Ext 2").grid(row=7, + column=0, + sticky=W) + Label(self.listFrame, text="Ext 2").grid(row=8, + column=0, + sticky=W) + + # Captions, labels and directio arrows in listFrame + self.name_list.append("Kelvin") + self.name_list.append("Kelvin Error") + self.name_list.append("Ext 1") + self.name_list.append("Ext 2") + + Label(self.listFrame, text=" --->").grid(row=0, column=1, sticky=W) + Label(self.listFrame, text=" <---").grid(row=1, column=1, sticky=W) + Label(self.listFrame, text=" --->").grid(row=2, column=1, sticky=W) + Label(self.listFrame, text=" <---").grid(row=3, column=1, sticky=W) + Label(self.listFrame, text=" --->").grid(row=5, column=1, sticky=W) + Label(self.listFrame, text=" <---").grid(row=6, column=1, sticky=W) + Label(self.listFrame, text=" --->").grid(row=7, column=1, sticky=W) + Label(self.listFrame, text=" <---").grid(row=8, column=1, sticky=W) + + # Loop for creating the Checkboxs and the Color Options in listFrame + + # Variables for loop + self.rowcounter = 0 + self.addspace = 0 + + while self.rowcounter < 10: + + self.thumbs_temp_var = IntVar() + self.thumbs_temp = Checkbutton(self.listFrame, text="", + variable=self.thumbs_temp_var, + command=self.deselect_met) + + if self.rowcounter == 2: + self.thumbs_temp.grid(row=self.rowcounter, column=2,sticky=W+S) + else: + self.thumbs_temp.grid(row=self.rowcounter, column=2, sticky=W) + + self.thumb_list.append(self.thumbs_temp_var) + + self.line_fit_temp_var = IntVar() + self.line_fit_temp = Checkbutton(self.listFrame, text="", + variable=self.line_fit_temp_var, + command=self.select_met) + + self.line_fit_temp.grid(row=self.rowcounter, column=3, sticky=W) + + self.linefit_list.append(self.line_fit_temp_var) + + self.plane_fit_temp_var = IntVar() + + self.plane_fit_temp = Checkbutton(self.listFrame, text="", + variable=self.plane_fit_temp_var, + command=self.select_met) + + self.plane_fit_temp.grid(row=self.rowcounter, column=4, sticky=W) + + self.planefit_list.append(self.plane_fit_temp_var) + + self.invert_temp_var = IntVar() + + self.invert_temp = Checkbutton(self.listFrame, text="", + variable=self.invert_temp_var, + command=self.select_met) + + self.invert_temp.grid(row=self.rowcounter, column=5, sticky=W) + + self.invert_list.append(self.invert_temp_var) + + self.color_menu_var = StringVar() + self.color_menu = ttk.Combobox(self.listFrame, + textvariable=self.color_menu_var, + values=globvar_color_options, + width = globvar_ttk_Combobox, + state='readonly') + self.color_menu.grid(row=self.rowcounter, column=6, sticky=W) + self.color_menu.current(0) # set selection + self.color_menu.bind("<>", self.lost_focus) + + self.color_list.append(self.color_menu_var) + + self.rowcounter += 1 + self.addspace += 1 + + if self.addspace == 4: + self.addspace = 0 + Label(self.listFrame, text=" ").grid(row=self.rowcounter, + sticky=W) + self.rowcounter += 1 + + # Set counter of lines of FrameTwo + self.numChan = 15 + + # Remaining Buttons + self.button_dir = Button(master, text="Choose directory", + command=self.choose_dir) + self.button_dir.grid(row=2, column=0, sticky=W) + + self.button_pdf_dir = Button(master, text="Choose pdf path", + command=self.pdf_path_select) + self.button_pdf_dir.grid(row=2, column=1, sticky=W) + + self.button_run = Button(master, text="Run ...", + command=self.run_process) + self.button_run.grid(row=2, column=3, sticky=W) + + self.button_default = Button(master, text="Default", + command=self.default) + self.button_default.grid(row=2, column=4) + + self.button_info = Button(master, text="Info", + command=self.info) + self.button_info.grid(row=2, column=5) + + self.button_colours = Button(master, text="Show colour maps", + command=self.show_colours) + self.button_colours.grid(row=2, column=8) + + self.button_save = Button(master, text="Save configuration", + command=self.WriteConfigFile) + self.button_save.grid(row=2, column=10) + + self.button_okay = Button(master, text="Save & exit", + command=self.done) + self.button_okay.grid(row=2, column=12, sticky=E) + + # Read Config + self.ReadConfigFile() + + def ReadConfigFile(self): + + ''' + Method for reading the Config File + takes over the values in the GUI + ''' + + # From here on, the parameters from the config file are stored into + # the variables. + config_file_p = open(self.filepath_config, "r") + + # Read out if there are extra lines in the GUI + for line in config_file_p: + if "AddChannel" in line: + self.numChan = int(line[25:-1]) + + config_file_p.close() + + # Create the extra lines + self.accept_parts() + + config_file_p = open(self.filepath_config, "r") + + # Go to parameters. + for line in config_file_p: + if "Parameters" in line: + break + + channum = 0 + # The whole config file is read + for line in config_file_p: + + if "Rows" in line: + self.n_row.insert(0, line[25:-1]) + continue + if "Columns" in line: + self.n_col.insert(0, line[25:-1]) + continue + if "Rms" in line: + self.rms.insert(0, line[25:-1]) + continue + if "Image resolution" in line: + self.res.insert(0, line[25:-1]) + continue + if "Jpeg quality" in line: + self.jpeg.insert(0, line[25:-1]) + continue + if "X text position" in line: + self.text_x.insert(0, line[25:-1]) + continue + if "Y text position" in line: + self.text_y.insert(0, line[25:-1]) + continue + if "Text size" in line: + self.text_size.insert(0, line[25:-1]) + continue + if "Dx of text" in line: + self.text_block.insert(0, line[25:-1]) + continue + if "Font" in line: + # It might be that the user is typing into the ASCII config + # file some font, which is not existing. So here, we have to + # check this. If the font is not existing a standard font is + # used instead + if line[25:-1] in self.fonts: + self.font_menu.set(line[25:-1]) + continue +# if "Dy of text" in line: +# self.text_block_height.insert(0, line[25:-1]) + if "Deleting thumbs before" in line: + if line[25:-1] == "1": + self.thumbs_before.select() + continue + if "Deleting thumbs after" in line: + if line[25:-1] == "1": + self.thumbs_after.select() + continue + if "Date" in line: + if line[25:-1] == "1": + self.date.select() + continue + if "Size in nm" in line: + if line[25:-1] == "1": + self.sizenm.select() + continue + if "Size in px" in line: + if line[25:-1] == "1": + self.sizepx.select() + continue + if "Offset" in line: + if line[25:-1] == "1": + self.offset.select() + continue + if "Voltage" in line: + if line[25:-1] == "1": + self.voltage.select() + continue + if "Feedback" in line: + if line[25:-1] == "1": + self.feedback.select() + continue + if "Gain" in line: + if line[25:-1] == "1": + self.gain.select() + continue + if "Speed" in line: + if line[25:-1] == "1": + self.speed.select() + continue + if "Amplitude" in line: + if line[25:-1] == "1": + self.ampl.select() + continue + if "Angle" in line: + if line[25:-1] == "1": + self.angle.select() + continue + if "Extra directories" in line: + if line[25:-1] == "1": + self.extra_directories.select() + continue + if "Subdirs" in line: + if line[25:-1] == "1": + self.subdirs.select() + continue + if "Spektral Options" in line: + if line[25:-1] == "1": + self.skala.select() + continue + if "Format Options" in line: + if line[25:-1] == "1": + self.format.select() + continue + if "Peek Options" in line: + if line[25:-1] == "1": + self.peek.select() + continue + if "Minimum on zero Options" in line: + if line[25:-1] == "1": + self.minimum_on_zero.select() + continue + if "File extension" in line: + self.extension.insert(0, line[25:-1]) + continue + if "Master directory" in line: + self.masterdir.insert(0, line[25:-1]) + continue + if "Filename" in line: + self.filename.insert(0, line[25:-1]) + continue + if "Replace pdfs" in line: + if line[25:-1] == "1": + self.pdfs.select() + continue + if "Direction" in line: + if line[25:-1] == "0": + self.thumbs_all.select() + continue + if line[25:-1] == "1": + self.thumbs_for.select() + continue + if line[25:-1] == "2": + self.thumbs_back.select() + continue + if line[25:-1] == "3": + self.thumbs_none.select() + continue + if "Linefit" in line: + if line[25:-1] == "0": + self.lin_all.select() + continue + if line[25:-1] == "1": + self.lin_for.select() + continue + if line[25:-1] == "2": + self.lin_back.select() + continue + if line[25:-1] == "3": + self.lin_none.select() + continue + if "Planefit" in line: + if line[25:-1] == "0": + self.plane_all.select() + continue + if line[25:-1] == "1": + self.plane_for.select() + continue + if line[25:-1] == "2": + self.plane_back.select() + continue + if line[25:-1] == "3": + self.plane_none.select() + continue + if "Tooltips" in line: + if line[25:-1] == "0": + self.show_tipps.select() + self.sh_tooltips() + continue + if line[25:-1] == "1": + self.hide_tipps.select() + self.no_tooltips() + continue + + if "ChannelNumber" in line: + channum = int(line[25:-1]) + continue + + for i in range(channum): + stri = "Channelname " + str(i+1) + " " + if stri in line: + self.name_list[i+8].set(line[25:-1]) + + for i in range(len(self.thumb_list)): + stri = "Thumb " + str(i+1) + " " + if stri in line: + if line[25:-1] == "1": + self.thumb_list[i].set(line[25:-1]) + + for i in range(len(self.linefit_list)): + stri = "LineFit " + str(i+1) + " " + if stri in line: + if line[25:-1] == "1": + self.linefit_list[i].set(line[25:-1]) + + for i in range(len(self.planefit_list)): + stri = "PlaneFit " + str(i+1) + " " + if stri in line: + if line[25:-1] == "1": + self.planefit_list[i].set(line[25:-1]) + + for i in range(len(self.invert_list)): + stri = "Inverted " + str(i+ 1) + " " + if stri in line: + if line[25:-1] == "1": + self.invert_list[i].set(line[25:-1]) + + for j in range(len(self.color_list)): + stri = "Color " + str(j+1) + " " + if stri in line: + self.color_list[j].set(line[25:-1]) + + config_file_p.close() + + # change the Entry Objects in the Channel Frame to the new value + + self.change_entry() + + def WriteConfigFile(self): + + ''' + Method for saving the Config File + ''' + + # The parameters are first saved into a tmp file, which then replaces + # the config file. + + file_tmp = self.filepath_config[:-5] + "_tmp.conf" + + config_file_p = open(self.filepath_config, "r") + config_tmp_p = open(file_tmp, "w") + + for line in config_file_p: + if "==========" in line: + config_tmp_p.write(line) + break + else: + config_tmp_p.write(line) + + config_file_p.close() + + config_tmp_p.write("Rows : "+ + str(self.n_row.get())+"\n") + config_tmp_p.write("Columns : "+ + str(self.n_col.get())+"\n") + config_tmp_p.write("Rms : "+ + str(self.rms.get())+"\n") + config_tmp_p.write("Image resolution : "+ + str(self.res.get())+"\n") + config_tmp_p.write("Jpeg quality : "+ + str(self.jpeg.get())+"\n") + config_tmp_p.write("X text position : "+ + str(self.text_x.get())+"\n") + config_tmp_p.write("Y text position : "+ + str(self.text_y.get())+"\n") + config_tmp_p.write("Text size : "+ + str(self.text_size.get())+"\n") + config_tmp_p.write("Dx of text : "+ + str(self.text_block.get())+"\n") + config_tmp_p.write("Font : "+ + str(self.font_menu.get())+"\n") +# config_tmp_p.write("Dy of text : "+ +# str(self.text_block_height.get())+"\n") + config_tmp_p.write("Date : "+ + str(self.date_var.get())+"\n") + config_tmp_p.write("Size in nm : "+ + str(self.sizenm_var.get())+"\n") + config_tmp_p.write("Size in px : "+ + str(self.sizepx_var.get())+"\n") + config_tmp_p.write("Offset : "+ + str(self.offset_var.get())+"\n") + config_tmp_p.write("Voltage : "+ + str(self.voltage_var.get())+"\n") + config_tmp_p.write("Feedback : "+ + str(self.feedback_var.get())+"\n") + config_tmp_p.write("Gain : "+ + str(self.gain_var.get())+"\n") + config_tmp_p.write("Speed : "+ + str(self.speed_var.get())+"\n") + config_tmp_p.write("Amplitude : "+ + str(self.ampl_var.get())+"\n") + config_tmp_p.write("Angle : "+ + str(self.angle_var.get())+"\n") + config_tmp_p.write("Deleting thumbs before : "+ + str(self.thumbs_before_var.get())+"\n") + config_tmp_p.write("Deleting thumbs after : "+ + str(self.thumbs_after_var.get())+"\n") + config_tmp_p.write("Extra directories : "+ + str(self.extra_directories_var.get())+"\n") + config_tmp_p.write("Replace pdfs : "+ + str(self.pdfs_var.get())+"\n") + config_tmp_p.write("Subdirs : "+ + str(self.subdirs_var.get())+"\n") + config_tmp_p.write("Spektral Options : "+ + str(self.skala_var.get())+"\n") + config_tmp_p.write("Format Options : "+ + str(self.format_var.get())+"\n") + config_tmp_p.write("Peek Options : "+ + str(self.peek_var.get())+"\n") + config_tmp_p.write("Minimum on zero Options: "+ + str(self.minimum_on_zero_var.get())+"\n") +# config_tmp_p.write("RHK Special Options : "+ +# str(self.rhk_opt_var.get())+"\n") + config_tmp_p.write("Master directory : "+ + str(self.masterdir.get())+"\n") + config_tmp_p.write("Filename : "+ + str(self.filename.get())+"\n") + config_tmp_p.write("Color : "+ + str(self.color_menu.get())+"\n") + config_tmp_p.write("File extension : "+ + str(self.extension.get())+"\n") + config_tmp_p.write("Direction : "+ + str(self.thumbs_var.get())+"\n") + config_tmp_p.write("Linefit : "+ + str(self.lin_var.get())+"\n") + config_tmp_p.write("Planefit : "+ + str(self.plane_var.get())+"\n") + config_tmp_p.write("AddChannel : "+ + str(self.num)+"\n") + config_tmp_p.write("ChannelNumber : "+ + str(len(self.name_list)-8)+"\n") + config_tmp_p.write("Tooltips : "+ + str(self.tooltip_var.get())+"\n") + + for i in range(len(self.name_list)-8): + stri = "Channelname " + str(i+1) + + if int((i+1)/10) == 0: + stri += " : "+str(self.name_list[i+8].get())+"\n" + elif int((i+1)/10) < 10: + stri += " : "+str(self.name_list[i+8].get())+"\n" + elif int((i+1)/10) < 100: + stri += " : "+str(self.name_list[i+8].get())+"\n" + else: + continue + + config_tmp_p.write(stri) + + for i in range(len(self.thumb_list)): + stri = "Thumb " + str(i+1) + + if int((i+1)/10) == 0: + stri += " : "+str(self.thumb_list[i].get())+"\n" + elif int((i+1)/10) < 10: + stri += " : "+str(self.thumb_list[i].get())+"\n" + elif int((i+1)/10) < 100: + stri += " : "+str(self.thumb_list[i].get())+"\n" + else: + continue + + config_tmp_p.write(stri) + + for i in range(len(self.linefit_list)): + stri = "LineFit " + str(i+1) + + if int((i+1)/10) == 0: + stri += " : "+str(self.linefit_list[i].get())+"\n" + elif int((i+1)/10) < 10: + stri += " : "+str(self.linefit_list[i].get())+"\n" + elif int((i+1)/10) < 100: + stri += " : "+str(self.linefit_list[i].get())+"\n" + else: + continue + + config_tmp_p.write(stri) + + for i in range(len(self.planefit_list)): + stri = "PlaneFit " + str(i+1) + + if int((i+1)/10) == 0: + stri += " : "+str(self.planefit_list[i].get())+"\n" + elif int((i+1)/10) < 10: + stri += " : "+str(self.planefit_list[i].get())+"\n" + elif int((i+1)/10) < 100: + stri += " : "+str(self.planefit_list[i].get())+"\n" + else: + continue + + config_tmp_p.write(stri) + + for i in range(len(self.planefit_list)): + stri = "Inverted " + str(i+1) + + if int((i+1)/10) == 0: + stri += " : "+str(self.invert_list[i].get())+"\n" + elif int((i+1)/10) < 10: + stri += " : "+str(self.invert_list[i].get())+"\n" + elif int((i+1)/10) < 100: + stri += " : "+str(self.invert_list[i].get())+"\n" + else: + continue + + config_tmp_p.write(stri) + + for i in range(len(self.color_list)): + stri = "Color " + str(i+1) + + if int((i+1)/10) == 0: + stri += " : "+str(self.color_list[i].get())+"\n" + elif int((i+1)/10) < 10: + stri += " : "+str(self.color_list[i].get())+"\n" + elif int((i+1)/10) < 100: + stri += " : "+str(self.color_list[i].get())+"\n" + else: + continue + + config_tmp_p.write(stri) + + config_tmp_p.close() + + os.remove(self.filepath_config) + os.rename(file_tmp, self.filepath_config) + + def default(self): + + ''' + Sets all Options to its default values + ''' + + # The default values are set. + self.n_col.delete(0, END) + self.n_col.insert(0, "4") + self.n_row.delete(0, END) + self.n_row.insert(0, "6") + self.row_update("") + self.col_update("") + self.rms.delete(0, END) + self.rms.insert(0, "2") + self.res.delete(0, END) + self.res.insert(0, "100") + self.jpeg.delete(0, END) + self.jpeg.insert(0, "40") + self.text_size.delete(0, END) + self.text_size.insert(0, "11") + self.text_x.delete(0, END) + self.text_x.insert(0, "0") + self.text_y.delete(0, END) + self.text_y.insert(0, "0") + self.text_block.delete(0, END) + self.text_block.insert(0, "0") +# self.text_block_height.delete(0, END) +# self.text_block_height.insert(0, "0")deselect_met + self.date.select() + self.sizenm.select() + self.sizepx.select() + self.offset.select() + self.voltage.select() + self.feedback.select() + self.gain.select() + self.speed.select() + self.ampl.select() + self.angle.select() + self.thumbs_before.select() + self.thumbs_after.select() + self.extra_directories.deselect() + self.pdfs.deselect() + self.subdirs.deselect() +# self.rhk_opt.select() + + self.thumbs_all.select() + self.thumbs_for.deselect() + self.thumbs_back.deselect() + self.thumbs_none.deselect() + self.lin_all.select() + self.lin_for.deselect() + self.lin_back.deselect() + self.lin_none.deselect() + self.plane_all.select() + self.plane_for.deselect() + self.plane_back.deselect() + self.plane_none.deselect() + + self.masterdir.delete(0, END) + self.masterdir.insert(0, "") + self.extension.delete(0, END) + self.extension.insert(0, "") + + for i in range(2,6): + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if i == 2: + wid.select() + elif i == 3: + wid.select() + elif i == 4: + wid.deselect() + elif i == 5: + wid.deselect() + + for i in range(2,6): + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if i == 2: + wid.select() + elif i == 3: + wid.select() + elif i == 4: + wid.deselect() + elif i == 5: + wid.deselect() + + # The following methods let you select or deselect the Checkboxes in + # frameOne and listFrame + + # Select Thumbs Methods + def select_thumbs_all(self): + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=2)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=2)[0] + if isinstance(wid, Checkbutton): + wid.select() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=2)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=2)[0] + if isinstance(wid, Checkbutton): + wid.select() + + def select_thumbs_for(self): + + for i in range(2,6): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + if i == 2: + wid.select() + else: + dir_count = 0 + if i == 2: + wid.deselect() + elif i == 3: + wid.deselect() + elif i == 4: + wid.deselect() + elif i == 5: + wid.deselect() + + for i in range(2,6): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + if i == 2: + wid.select() + else: + dir_count = 0 + if i == 2: + wid.deselect() + elif i == 3: + wid.deselect() + elif i == 4: + wid.deselect() + elif i == 5: + wid.deselect() + + def select_thumbs_back(self): + + for i in range(2,6): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + if i == 2: + wid.select() + else: + dir_count = 1 + if i == 2: + wid.deselect() + elif i == 3: + wid.deselect() + elif i == 4: + wid.deselect() + elif i == 5: + wid.deselect() + + for i in range(2,5): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + if i == 2: + wid.select() + else: + dir_count = 1 + if i == 2: + wid.deselect() + elif i == 3: + wid.deselect() + elif i == 4: + wid.deselect() + elif i == 5: + wid.deselect() + + def select_thumbs_none(self): + + self.lin_none.select() + self.select_lin_none() + + self.plane_none.select() + self.select_plane_none() + + self.invert_none.select() + self.select_invert_none() + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=2)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=2)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=2)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=2)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + + # Select Linefit Methods + + def select_lin_all(self): + + self.thumbs_all.select() + self.select_thumbs_all() + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=3)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=3)[0] + if isinstance(wid, Checkbutton): + wid.select() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=3)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=3)[0] + if isinstance(wid, Checkbutton): + wid.select() + + def select_lin_for(self): + + for i in range(2,4): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + wid.select() + else: + dir_count = 0 + if i == 2: + continue + elif i == 3: + wid.deselect() + + for i in range(2,4): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + wid.select() + else: + dir_count = 0 + if i == 2: + continue + elif i == 3: + wid.deselect() + + def select_lin_back(self): + + for i in range(2,4): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + wid.select() + else: + dir_count = 1 + if i == 2: + continue + elif i == 3: + wid.deselect() + + for i in range(2,4): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + wid.select() + else: + dir_count = 1 + if i == 2: + continue + elif i == 3: + wid.deselect() + + def select_lin_none(self): + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=3)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=3)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=3)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=3)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + # Select Planefit Methods + + def select_plane_all(self): + + self.thumbs_all.select() + self.select_thumbs_all() + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=4)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=4)[0] + if isinstance(wid, Checkbutton): + wid.select() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=4)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=4)[0] + if isinstance(wid, Checkbutton): + wid.select() + + def select_plane_for(self): + + for i in range(2,5): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + if i == 2 or i == 4: + wid.select() + else: + continue + else: + dir_count = 0 + if i == 2 or i == 3: + continue + elif i == 4: + wid.deselect() + + for i in range(2,5): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + if i == 2 or i == 4: + wid.select() + else: + continue + else: + dir_count = 0 + if i == 2 or i == 3: + continue + elif i == 4: + wid.deselect() + + + def select_plane_back(self): + + for i in range(2,5): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + if i == 2 or i == 4: + wid.select() + else: + continue + else: + dir_count = 1 + if i == 2 or i == 3: + continue + elif i == 4: + wid.deselect() + + for i in range(2,5): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + if i == 2 or i == 4: + wid.select() + else: + continue + else: + dir_count = 1 + if i == 2 or i == 3: + continue + elif i == 4: + wid.deselect() + + def select_plane_none(self): + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=4)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=4)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=4)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=4)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + # Select Invert Methods + + def select_invert_all(self): + + self.thumbs_all.select() + self.select_thumbs_all() + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=5)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=5)[0] + if isinstance(wid, Checkbutton): + wid.select() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=5)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=5)[0] + if isinstance(wid, Checkbutton): + wid.select() + + def select_invert_for(self): + + for i in range(2,6): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + if i == 2 or i == 5: + wid.select() + else: + continue + else: + dir_count = 0 + if i == 2 or i == 3 or i == 4: + continue + elif i == 5: + wid.deselect() + + for i in range(2,6): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 0: + dir_count = 1 + if i == 2 or i == 5: + wid.select() + else: + continue + else: + dir_count = 0 + if i == 2 or i == 3 or i == 4: + continue + elif i == 5: + wid.deselect() + + def select_invert_back(self): + + for i in range(2,6): + dir_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=i)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + if i == 2 or i == 5: + wid.select() + else: + continue + else: + dir_count = 1 + if i == 2 or i == 3 or i == 4: + continue + elif i == 5: + wid.deselect() + + for i in range(2,6): + dir_count = 0 + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=i)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=i)[0] + if isinstance(wid, Checkbutton): + if dir_count == 1: + dir_count = 0 + if i == 2 or i == 5: + wid.select() + else: + continue + else: + dir_count = 1 + if i == 2 or i == 3 or i == 4: + continue + elif i == 5: + wid.deselect() + + def select_invert_none(self): + + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=5)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=5)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=5)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=5)[0] + if isinstance(wid, Checkbutton): + wid.deselect() + + + # Checkbox options + + def select_met(self): + + list_count = 0 + for j in range(2,21): + if len(self.frameOne.grid_slaves(row=j, column=2)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=2)[0] + if isinstance(wid, Checkbutton): + if (self.linefit_list[list_count].get() or + self.planefit_list[list_count].get() or + self.invert_list[list_count].get()): + wid.select() + list_count += 1 + + for j in range(self.num): + if len(self.listFrame.grid_slaves(row=j, column=2)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=2)[0] + if isinstance(wid, Checkbutton): + if (self.linefit_list[list_count].get() or + self.planefit_list[list_count].get() or + self.invert_list[list_count].get()): + wid.select() + list_count += 1 + + def deselect_met(self): + + list_count = 0 + for j in range(2,21): + + if len(self.frameOne.grid_slaves(row=j, column=3)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=3)[0] + if isinstance(wid, Checkbutton): + if not self.thumb_list[list_count].get(): + wid.deselect() + + + if len(self.frameOne.grid_slaves(row=j, column=4)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=4)[0] + if isinstance(wid, Checkbutton): + if not self.thumb_list[list_count].get(): + wid.deselect() + + if len(self.frameOne.grid_slaves(row=j, column=5)) != 0: + wid = self.frameOne.grid_slaves(row=j, column=5)[0] + if isinstance(wid, Checkbutton): + if not self.thumb_list[list_count].get(): + wid.deselect() + list_count += 1 + + for j in range(self.num): + + if len(self.listFrame.grid_slaves(row=j, column=3)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=3)[0] + if isinstance(wid, Checkbutton): + if not self.thumb_list[list_count].get(): + wid.deselect() + + + if len(self.listFrame.grid_slaves(row=j, column=4)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=4)[0] + if isinstance(wid, Checkbutton): + if not self.thumb_list[list_count].get(): + wid.deselect() + + if len(self.listFrame.grid_slaves(row=j, column=5)) != 0: + wid = self.listFrame.grid_slaves(row=j, column=5)[0] + if isinstance(wid, Checkbutton): + if not self.thumb_list[list_count].get(): + wid.deselect() + list_count += 1 + + # Choose dir and choose pdf Path Methods + + def choose_dir(self): + + ''' + Let one specific the working path + ''' + + config_file_p = open(self.filepath_config, "r") + for line in config_file_p: + if "Last directory:" in line: + position = str.find(line, ":") + start_directory = line[position+2:-1] + config_file_p.close() + + self.working_directory = filedialog.askdirectory( + initialdir=start_directory, + title='Select a directory') + + config_file_p = open(self.filepath_config, "r") + file_tmp = self.filepath_config[:-5] + "_tmp.conf" + config_tmp_p = open(file_tmp, "w") + + for line in config_file_p: + if "Last directory:" in line: + string = "Last directory: "+self.working_directory+"\n" + config_tmp_p.write(string) + else: + config_tmp_p.write(line) + + config_file_p.close() + config_tmp_p.close() + + os.remove(self.filepath_config) + os.rename(file_tmp, self.filepath_config) + + def pdf_path_select(self): + + ''' + Let one specific the pdf path + ''' + + config_file_p = open(self.filepath_config, "r") + for line in config_file_p: + if "PDF Path:" in line: + position = str.find(line, ":") + start_directory = line[position+2:-1] + config_file_p.close() + + self.pdf_path = filedialog.askdirectory( + initialdir=start_directory, + title='Select a directory') + + config_file_p = open(self.filepath_config, "r") + file_tmp = self.filepath_config[:-5] + "_tmp.conf" + config_tmp_p = open(file_tmp, "w") + + for line in config_file_p: + if "PDF Path:" in line: + string = "PDF Path: "+self.pdf_path+"\n" + config_tmp_p.write(string) + else: + config_tmp_p.write(line) + + config_file_p.close() + config_tmp_p.close() + + os.remove(self.filepath_config) + os.rename(file_tmp, self.filepath_config) + + def run_process(self): + + ''' + Starts the working process + ''' + + if (self.working_directory == ""): + tkMessageBox.showinfo(globvar_name, + "You need to load a directory !") + + # Saving all GUI-Variables to global Variables + else: + + globvar_ThumbPara.row = int(self.n_row.get()) + globvar_ThumbPara.col = int(self.n_col.get()) + globvar_ThumbPara.rms = self.rms.get() + globvar_ThumbPara.res = self.res.get() + globvar_ThumbPara.font = self.font_menu.get() + globvar_ThumbPara.jpeg = self.jpeg.get() + globvar_ThumbPara.thumbs_before = self.thumbs_before_var.get() + globvar_ThumbPara.thumbs_after = self.thumbs_after_var.get() + globvar_ThumbPara.peek = self.peek_var.get() + globvar_ThumbPara.minimum_on_zero= self.minimum_on_zero_var.get() + globvar_ThumbPara.png = self.format_var.get() + globvar_ThumbPara.date = self.date_var.get() + globvar_ThumbPara.sizenm = self.sizenm_var.get() + globvar_ThumbPara.sizepx = self.sizepx_var.get() + globvar_ThumbPara.offset = self.offset_var.get() + globvar_ThumbPara.voltage = self.voltage_var.get() + globvar_ThumbPara.feedback = self.feedback_var.get() + globvar_ThumbPara.gain = self.gain_var.get() + globvar_ThumbPara.speed = self.speed_var.get() + globvar_ThumbPara.ampl = self.ampl_var.get() + globvar_ThumbPara.text_block = self.text_block.get() +# globvar_ThumbPara.text_block_height = self.text_block_height.get() + globvar_ThumbPara.text_size = self.text_size.get() + globvar_ThumbPara.text_x = str(float( \ + self.text_x.get())/100.0) + globvar_ThumbPara.text_y = str(float( \ + self.text_y.get())/100.0) + globvar_ThumbPara.angle = self.angle_var.get() + globvar_ThumbPara.extra_direct = self.extra_directories_var.get() + globvar_ThumbPara.pdfs = self.pdfs_var.get() + globvar_ThumbPara.subdirs = self.subdirs_var.get() + globvar_ThumbPara.masterdir = self.masterdir.get() + globvar_ThumbPara.extension = self.extension.get() + globvar_ThumbPara.filename = self.filename.get() + globvar_ThumbPara.spektra = self.skala_var.get() + + globvar_ThumbPara.channel_names = [i.get() for i in \ + self.name_list[8:]] + + globvar_ThumbPara.thumbs = [i.get() for i in \ + self.thumb_list] + globvar_ThumbPara.line_fit = [i.get() for i in \ + self.linefit_list] + globvar_ThumbPara.plane_fit = [i.get() for i in \ + self.planefit_list] + globvar_ThumbPara.invert = [i.get() for i in \ + self.invert_list] + + globvar_ThumbPara.geometry_x.append(globvar_thumb_size_x * + float(globvar_ThumbPara.res)) + globvar_ThumbPara.geometry_y.append(globvar_thumb_size_y * + float(globvar_ThumbPara.res)) + + globvar_AFMdir.pdf_path = self.pdf_path + + globvar_ThumbPara.colors = [define_color(i.get()) for i in \ + self.color_list] + + # Renew Config File with new Values + self.WriteConfigFile() + + # Start working process + start = timer() + + initialize_and_go(self.working_directory, None) + + end = timer() + seconds = timedelta(seconds=end - start) + time_passed = datetime(1,1,1) + seconds + print(globvar_timepassed_1 + + globvar_timepassed_2 + % (time_passed.day-1, + time_passed.hour, + time_passed.minute, + (end - start) % 60)) + + messagebox.showinfo(globvar_name, "Finished !") + + def done(self): + + ''' + Finish all remaining tasks + ''' + + # Update (write) the config file. + self.WriteConfigFile() + + # End of all + self.master.destroy() + + def info(self): + + ''' + Shows info box + ''' + + messagebox.showinfo(globvar_name, globvar_note) + + # Show a plot of gradients. See Colours.py + def show_colours(self): + + plot_color_gradients() + + # This definition clarifies, which fonts are available on the system and + # which of the preferred fonts in 'globvar_fonts' is in the list of + # available_fonts. Return the list of available preferred fonts. + def get_fonts(self): + + + # 2018-09-12: This is used to sort bad fonts which may + # break the code. + GO = True; + avaible_fonts = [] + for fontdetail in matplotlib.font_manager.findSystemFonts(): + for bad_font in globvar_bad_fonts: + if bad_font in fontdetail: + print(globvar_spaces + "Bad font: " + bad_font + "\n") + GO = False + break + + if GO == False: + continue + + font = matplotlib.font_manager.FontProperties(fname=fontdetail).get_name() + avaible_fonts.append(font) + + font_list = [] + for font in globvar_fonts: + if font in avaible_fonts: + font_list.append(font) + + return font_list + + # _________________ Event Methods + # _________________ The following methods are for the binding to widgets + + # Focus binding + def callback(self,event): + self.focus_set() + + def lost_focus(self,event): + self.master.focus_set() + + # Change label and change entry bindings + def change_label(self,event): + skip_next = False + label_counter = 8 + ent = "" + + for i in range(10,self.num): + + if skip_next: + skip_next = False + continue + + numwid = len(self.listFrame.grid_slaves(row=i, column=0)) + if numwid != 0: + wid = self.listFrame.grid_slaves(row=i, column=0) + if isinstance(wid[0], Entry): + ent = wid[0].get() + elif isinstance(wid[0], Label): + if ent != self.name_list[label_counter].get(): + self.name_list[label_counter].set(ent) + ent = "" + label_counter += 1 + if label_counter%2 == 0: + skip_next = True + + def change_entry(self): + label_counter = 8 + + for i in range(10,self.num): + if len(self.listFrame.grid_slaves(row=i, column=0)) != 0: + wid = self.listFrame.grid_slaves(row=i, column=0) + if isinstance(wid[0], Entry): + wid[0].insert(0,self.name_list[label_counter].get()) + label_counter += 1 + else: + continue + + # Tooltips bindings + + def sh_tooltips(self): + + # tooltips + # Arrangement + self.n_col.bind("", self.row_update, add="+") + self.n_row.bind("", self.col_update, add="+") + self.n_col.bind("", self.row_update, add="+") + self.n_row.bind("", self.col_update, add="+") + + create_tool_tip(self.n_col, self.col_tip()) + create_tool_tip(self.n_row, self.row_tip()) + + create_tool_tip(self.rms, TT_rms) + create_tool_tip(self.res, TT_res) + create_tool_tip(self.jpeg, TT_qual) + + # Position + create_tool_tip(self.text_size, TT_size) + create_tool_tip(self.text_x, TT_dx_pos) + create_tool_tip(self.text_y, TT_dy_pos) + create_tool_tip(self.text_block, TT_dw) + + # Specification + create_tool_tip(self.extension, TT_file_ex) + create_tool_tip(self.masterdir, TT_master_dir) + create_tool_tip(self.filename, TT_filename) + + # Parameters + create_tool_tip(self.date, TT_date) + create_tool_tip(self.sizenm, TT_size_nm) + create_tool_tip(self.sizepx, TT_size_px) + create_tool_tip(self.offset, TT_off) + create_tool_tip(self.voltage, TT_vol) + create_tool_tip(self.feedback, TT_feed) + create_tool_tip(self.gain, TT_loop) + create_tool_tip(self.speed, TT_speed) + create_tool_tip(self.ampl, TT_amp) + create_tool_tip(self.angle, TT_angle) + + # Other + create_tool_tip(self.thumbs_before, TT_thumb_before) + create_tool_tip(self.thumbs_after, TT_thumb_after) + create_tool_tip(self.extra_directories, TT_extra_dir) + create_tool_tip(self.pdfs, TT_pdfs) + create_tool_tip(self.subdirs, TT_subdirs) + create_tool_tip(self.format, TT_png) + create_tool_tip(self.skala, TT_spektral) + create_tool_tip(self.peek, TT_peek) + create_tool_tip(self.minimum_on_zero, TT_minimum_on_zero) +# create_tool_tip(self.rhk_opt, TT_Reich) + + def no_tooltips(self): + + # Special Unbinding for column and row + self.n_col.unbind("") + self.n_row.unbind("") + self.n_col.unbind("") + self.n_row.unbind("") + self.n_col.bind("", self.lost_focus) + self.n_row.bind("", self.lost_focus) + + # Arrangement + self.n_col.unbind('') + self.n_col.unbind('') + self.n_row.unbind('') + self.n_row.unbind('') + self.rms.unbind('') + self.rms.unbind('') + self.res.unbind('') + self.res.unbind('') + self.jpeg.unbind('') + self.jpeg.unbind('') + + # Position + self.text_size.unbind('') + self.text_size.unbind('') + self.text_x.unbind('') + self.text_x.unbind('') + self.text_y.unbind('') + self.text_y.unbind('') + self.text_block.unbind('') + self.text_block.unbind('') + + # Specification + self.extension.unbind('') + self.extension.unbind('') + self.masterdir.unbind('') + self.masterdir.unbind('') + self.filename.unbind('') + self.filename.unbind('') + + # Parameters + self.date.unbind('') + self.date.unbind('') + self.sizenm.unbind('') + self.sizenm.unbind('') + self.sizepx.unbind('') + self.sizepx.unbind('') + self.offset.unbind('') + self.offset.unbind('') + self.voltage.unbind('') + self.voltage.unbind('') + self.feedback.unbind('') + self.feedback.unbind('') + self.gain.unbind('') + self.gain.unbind('') + self.speed.unbind('') + self.speed.unbind('') + self.ampl.unbind('') + self.ampl.unbind('') + self.angle.unbind('') + self.angle.unbind('') + + # Other + self.thumbs_before.unbind('') + self.thumbs_before.unbind('') + self.thumbs_after.unbind('') + self.thumbs_after.unbind('') + self.extra_directories.unbind('') + self.extra_directories.unbind('') + self.pdfs.unbind('') + self.pdfs.unbind('') + self.subdirs.unbind('') + self.subdirs.unbind('') + self.format.unbind('') + self.format.unbind('') + self.skala.unbind('') + self.skala.unbind('') + self.peek.unbind('') + self.peek.unbind('') + self.minimum_on_zero.unbind('') + self.minimum_on_zero.unbind('') + + def row_update(self,event): + + create_tool_tip(self.n_row, self.row_tip()) + + def col_update(self,event): + + create_tool_tip(self.n_col, self.col_tip()) + + def col_tip(self): + + st = ("DIN A4 portrait format: " + + "{0:.2f}".format(297.0/(210.0/int(self.n_row.get())))) + st += " to " + self.n_row.get() + "\n" + st += ("DIN A4 landscape format: " + + "{0:.2f}".format(210.0/(297.0/int(self.n_row.get())))) + st += " to " + self.n_row.get() + + return TT_n_col + st + + def row_tip(self): + + st = "DIN A4 portrait format: " + self.n_col.get() + st += (" to " + "{0:.2f}".format(210.0/(297.0/int(self.n_col.get()))) + + "\n") + st += "DIN A4 landscape format: " + self.n_col.get() + st += " to " + "{0:.2f}".format(297.0/(210.0/int(self.n_col.get()))) + + return TT_n_row + st + + # Mousewheel binding + def mouse_wheel(self,event): + if self.op_sys == "Windows" or self.op_sys == "Linux": + # This is for Linux + if event.num == 5: + self.canvas.yview_scroll(1,"units") + elif event.num == 4: + self.canvas.yview_scroll(-1,"units") + # This is for Windows... + else: + self.canvas.yview_scroll(-1*(event.delta/120), "units") + elif self.op_sys == "Darwin": + self.canvas.yview_scroll(-1*(event.delta), "units") + else: + self.canvas.yview_scroll(-1*(event.delta/120), "units") + + def activate_mousewheel(self, event): + # Mousewheel binding + # With Windows and Mac OS + self.canvas.bind_all("", self.mouse_wheel) + # with Linux OS + self.canvas.bind_all("", self.mouse_wheel) + self.canvas.bind_all("", self.mouse_wheel) + + def deactivate_mousewheel(self, event): + # Mousewheel unbinding + # With Windows and Mac OS + self.canvas.unbind_all("") + # with Linux OS + self.canvas.unbind_all("") + self.canvas.unbind_all("") + + # The following methods create and delete Entry lines + + # Scrollbar Frame + def AuxscrollFunction(self,event): + # You need to set a max size for frameTwo. Otherwise, it will grow as + # needed, and the scrollbar does not act. + if self.op_sys == "Linux": + self.canvas.configure(scrollregion=self.canvas.bbox("all"), + width=600, + height=200) + + elif self.op_sys == "Windows": + self.canvas.configure(scrollregion=self.canvas.bbox("all"), + width=550, + height=200) + + else: + self.canvas.configure(scrollregion=self.canvas.bbox("all"), + width=600, + height=200) + + def accept_parts(self): + + self.accept_parts_ok() + # The grid scrollbar is in master, because the user had defined the + # numer of pieces. + self.scrollb.grid(row=2, column=1, sticky='nsew') + + def accept_parts_ok(self): + + self.num = 10 + self.addtime = 0 + + while self.num < self.numChan-1: + + self.addtime += 2 + + extra_channel = Entry(self.listFrame, width=12) + extra_channel.delete(0, END) + extra_channel.bind("", self.change_label) + extra_channel.bind("", self.callback) + extra_channel.bind("", self.lost_focus) + extra_channel.grid(row=self.num, column=0, sticky=W) + self.label_text = StringVar() + Label(self.listFrame, + textvariable=self.label_text).grid(row=self.num+1, + column=0, + sticky=W) + self.name_list.append(self.label_text) + + + Label(self.listFrame, text=" --->").grid(row=self.num, + column=1, + sticky=W) + Label(self.listFrame, text=" <---").grid(row=self.num+1, + column=1, + sticky=W) + + self.thumbs_temp1_var = IntVar() + self.thumbs_temp1 = Checkbutton(self.listFrame, text="", + variable=self.thumbs_temp1_var, + command=self.deselect_met) + self.thumbs_temp1.grid(row=self.num, column=2, sticky=W) + self.thumb_list.append(self.thumbs_temp1_var) + + self.thumbs_temp2_var = IntVar() + self.thumbs_temp2 = Checkbutton(self.listFrame, text="", + variable=self.thumbs_temp2_var, + command=self.deselect_met) + self.thumbs_temp2.grid(row=self.num+1, column=2, sticky=W) + self.thumb_list.append(self.thumbs_temp2_var) + + self.line_fit_temp1_var = IntVar() + self.line_fit_temp1 = Checkbutton(self.listFrame, text="", + variable=self.line_fit_temp1_var, + command=self.select_met) + self.line_fit_temp1.grid(row=self.num, column=3, sticky=W) + self.linefit_list.append(self.line_fit_temp1_var) + + self.line_fit_temp2_var = IntVar() + self.line_fit_temp2 = Checkbutton(self.listFrame, text="", + variable=self.line_fit_temp2_var, + command=self.select_met) + self.line_fit_temp2.grid(row=self.num+1, column=3, sticky=W) + self.linefit_list.append(self.line_fit_temp2_var) + + self.plane_fit_temp1_var = IntVar() + self.plane_fit_temp1 = Checkbutton(self.listFrame, text="", + variable= \ + self.plane_fit_temp1_var, + command=self.select_met) + self.plane_fit_temp1.grid(row=self.num, column=4, sticky=W) + self.planefit_list.append(self.plane_fit_temp1_var) + + self.plane_fit_temp2_var = IntVar() + self.plane_fit_temp2 = Checkbutton(self.listFrame, text="", + variable= \ + self.plane_fit_temp2_var, + command=self.select_met) + self.plane_fit_temp2.grid(row=self.num+1, column=4, sticky=W) + self.planefit_list.append(self.plane_fit_temp2_var) + + self.invert_temp1_var = IntVar() + self.invert_temp1 = Checkbutton(self.listFrame, text="", + variable=self.invert_temp1_var, + command=self.select_met) + self.invert_temp1.grid(row=self.num, column=5, sticky=W) + self.invert_list.append(self.invert_temp1_var) + + self.invert_temp2_var = IntVar() + self.invert_temp2 = Checkbutton(self.listFrame, text="", + variable=self.invert_temp2_var, + command=self.select_met) + self.invert_temp2.grid(row=self.num+1, column=5, sticky=W) + self.invert_list.append(self.invert_temp2_var) + + self.color_menu_tmp1_var = StringVar() + self.color_menu_tmp1 = ttk.Combobox(self.listFrame, + textvariable= \ + self.color_menu_tmp1_var, + values=globvar_color_options, + width = globvar_ttk_Combobox, + state='readonly') + self.color_menu_tmp1.grid(row=self.num, column=6, sticky=W) + self.color_menu_tmp1.current(0) # set selection + self.color_menu_tmp1.bind("<>", self.lost_focus) + self.color_list.append(self.color_menu_tmp1_var) + + self.color_menu_tmp2_var = StringVar() + self.color_menu_tmp2 = ttk.Combobox(self.listFrame, + textvariable= \ + self.color_menu_tmp2_var, + values=globvar_color_options, + width = globvar_ttk_Combobox, + state='readonly') + self.color_menu_tmp2.grid(row=self.num+1, column=6, sticky=W) + self.color_menu_tmp2.current(0) # set selection + self.color_menu_tmp2.bind("<>", self.lost_focus) + self.color_list.append(self.color_menu_tmp2_var) + + self.num += 2 + + if self.addtime == 4: + self.addtime = 0 + Label(self.listFrame, text=" ").grid(row=self.num, sticky=W) + self.num += 1 + + # Buttons for adding or deleting rows + + self.addrow_button = Button(self.frameThree, text="Add row", + command=self.addrow, width=10) + self.addrow_button.grid(row=0, column=1, pady=(10,10)) + + self.deleterow_button = Button(self.frameThree, text="Delete row", + command=self.deleterow, width=10) + self.deleterow_button.grid(row=0, column=2, pady=(10,10)) + + def addrow(self): + + self.addtime += 2 + + extra_channel = Entry(self.listFrame, width=12) + extra_channel.delete(0, END) + extra_channel.bind("", self.change_label) + extra_channel.bind("", self.callback) + extra_channel.bind("", self.lost_focus) + extra_channel.grid(row=self.num, column=0, sticky=W) + self.label_text = StringVar() + Label(self.listFrame,textvariable=self.label_text).grid(row=self.num+1, + column=0, + sticky=W) + self.name_list.append(self.label_text) + + + Label(self.listFrame, text=" --->").grid(row=self.num, + column=1, + sticky=W) + Label(self.listFrame, text=" <---").grid(row=self.num+1, + column=1, + sticky=W) + + self.thumbs_temp1_var = IntVar() + self.thumbs_temp1 = Checkbutton(self.listFrame, text="", + variable=self.thumbs_temp1_var, + command=self.deselect_met) + self.thumbs_temp1.grid(row=self.num, column=2, sticky=W) + self.thumb_list.append(self.thumbs_temp1_var) + + self.thumbs_temp2_var = IntVar() + self.thumbs_temp2 = Checkbutton(self.listFrame, text="", + variable=self.thumbs_temp2_var, + command=self.deselect_met) + self.thumbs_temp2.grid(row=self.num+1, column=2, sticky=W) + self.thumb_list.append(self.thumbs_temp2_var) + + self.line_fit_temp1_var = IntVar() + self.line_fit_temp1 = Checkbutton(self.listFrame, text="", + variable=self.line_fit_temp1_var, + command=self.select_met) + self.line_fit_temp1.grid(row=self.num, column=3, sticky=W) + self.linefit_list.append(self.line_fit_temp1_var) + + self.line_fit_temp2_var = IntVar() + self.line_fit_temp2 = Checkbutton(self.listFrame, text="", + variable=self.line_fit_temp2_var, + command=self.select_met) + self.line_fit_temp2.grid(row=self.num+1, column=3, sticky=W) + self.linefit_list.append(self.line_fit_temp2_var) + + self.plane_fit_temp1_var = IntVar() + self.plane_fit_temp1 = Checkbutton(self.listFrame, text="", + variable=self.plane_fit_temp1_var, + command=self.select_met) + self.plane_fit_temp1.grid(row=self.num, column=4, sticky=W) + self.planefit_list.append(self.plane_fit_temp1_var) + + self.plane_fit_temp2_var = IntVar() + self.plane_fit_temp2 = Checkbutton(self.listFrame, text="", + variable=self.plane_fit_temp2_var, + command=self.select_met) + self.plane_fit_temp2.grid(row=self.num+1, column=4, sticky=W) + self.planefit_list.append(self.plane_fit_temp2_var) + + self.invert_temp1_var = IntVar() + self.invert_temp1 = Checkbutton(self.listFrame, text="", + variable=self.invert_temp1_var, + command=self.select_met) + self.invert_temp1.grid(row=self.num, column=5, sticky=W) + self.invert_list.append(self.invert_temp1_var) + + self.invert_temp2_var = IntVar() + self.invert_temp2 = Checkbutton(self.listFrame, text="", + variable=self.invert_temp2_var, + command=self.select_met) + self.invert_temp2.grid(row=self.num+1, column=5, sticky=W) + self.invert_list.append(self.invert_temp2_var) + + self.color_menu_tmp1_var = StringVar() + self.color_menu_tmp1 = ttk.Combobox(self.listFrame, + textvariable= \ + self.color_menu_tmp1_var, + values=globvar_color_options, + width = globvar_ttk_Combobox, + state='readonly') + self.color_menu_tmp1.grid(row=self.num, column=6, sticky=W) + self.color_menu_tmp1.current(0) # set selection + self.color_menu_tmp1.bind("<>", self.lost_focus) + self.color_list.append(self.color_menu_tmp1_var) + + self.color_menu_tmp2_var = StringVar() + self.color_menu_tmp2 = ttk.Combobox(self.listFrame, + textvariable= \ + self.color_menu_tmp2_var, + values=globvar_color_options, + width = globvar_ttk_Combobox, + state='readonly') + self.color_menu_tmp2.grid(row=self.num+1, column=6, sticky=W) + self.color_menu_tmp2.current(0) # set selection + self.color_menu_tmp2.bind("<>", self.lost_focus) + self.color_list.append(self.color_menu_tmp2_var) + + self.num = int(self.num)+2 + + if self.addtime == 4: + self.addtime = 0 + Label(self.listFrame, text=" ").grid(row=self.num, sticky=W) + self.num += 1 + + def deleterow(self): + if not self.num == 15: + self.count = 2 + + if self.addtime == 0: + self.count += 1 + self.addtime = 2 + else: + self.addtime = 0 + + for numx in range(self.num-self.count, self.num): + for numy in range(7): + numwid = len(self.listFrame.grid_slaves(row=numx, + column=numy)) + if numwid != 0: + wid = self.listFrame.grid_slaves(row=numx, + column=numy) + for numwidindex in range(numwid): + wid[numwidindex].grid_remove() + + self.name_list.pop() + self.thumb_list.pop() + self.thumb_list.pop() + self.linefit_list.pop() + self.linefit_list.pop() + self.planefit_list.pop() + self.planefit_list.pop() + self.invert_list.pop() + self.invert_list.pop() + self.c.pop() + self.color_list.pop() + + self.num -= self.count + + +# ________________________________________________________________________ Main + + +if __name__ == '__main__': + + print(globvar_console) + + # Command line: are there any options? + gui, master_directory, config_file = command_line() + + # If the GUI shall be started then do so ... + if gui: + root = Tk() + app = MyDialog(root) + root.update() + + screen_width = root.winfo_screenwidth() + screen_height = root.winfo_screenheight() + window_width = root.winfo_width() + window_height = root.winfo_height() + + root.geometry('+%d+%d' % ((screen_width - window_width) / 2, + (screen_height - window_height) / 2)) + + root.mainloop() + + # If not, then start AFM_thumbs without GUI and apply it on the master + # directory with the options described in the config file of AFM_thumbs. + else: + + if master_directory != None: + + start = timer() + + initialize_and_go(master_directory, config_file) + + end = timer() + seconds = timedelta(seconds=end - start) + time_passed = datetime(1,1,1) + seconds + print(globvar_timepassed_1 + + globvar_timepassed_2 + % (time_passed.day-1, + time_passed.hour, + time_passed.minute, + (end - start) % 60)) + + diff --git a/AFM_thumbs.pyc b/AFM_thumbs.pyc new file mode 100755 index 0000000000000000000000000000000000000000..a9bb2b1df159cea5bdef0a7bbab3723b9125b68b GIT binary patch literal 60290 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/Channel.py b/AFM_thumbs/Channel.py new file mode 100755 index 0000000..1491ec8 --- /dev/null +++ b/AFM_thumbs/Channel.py @@ -0,0 +1,425 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import re + +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import ID_list +from AFM_thumbs.Variables import globvar_color_dict +from AFM_thumbs.Variables import globvar_spaces + + + +def rename_channel(name): + + if re.search(ID_list[0],name): + globvar_AFMdata.channel.append("Topography") + + elif re.search(ID_list[4],name): + if re.search(ID_list[5],name): + globvar_AFMdata.channel.append("filtered df") + else: + globvar_AFMdata.channel.append("df") + + elif re.search(ID_list[1],name): + globvar_AFMdata.channel.append("Amplitude") + + elif re.search(ID_list[6],name): + globvar_AFMdata.channel.append("Dissipation") + + elif re.search(ID_list[2],name): + if re.search(ID_list[3],name): + globvar_AFMdata.channel.append("Kelvin Error") + else: + globvar_AFMdata.channel.append("Kelvin") + + elif re.search(ID_list[8],name): + globvar_AFMdata.channel.append("Ext 1") + + elif re.search(ID_list[9],name): + globvar_AFMdata.channel.append("Ext 2") + + elif re.search(ID_list[7],name): + globvar_AFMdata.channel.append("Excitation") + + elif re.search(ID_list[10],name): + globvar_AFMdata.channel.append("Phase") + else: + found = False + for chan in globvar_ThumbPara.channel_names: + if not chan == "": + if re.search(chan,name): + found = True + + globvar_AFMdata.channel.append(name) + + if not found: + print(globvar_spaces + " Channel not found: " + name) + return False + + return True + + +def proceed_with(image_nr,direction): + + if globvar_AFMdata.channel[image_nr] == "Topography": + if direction == "forward" and globvar_ThumbPara.thumbs[0]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[1]: + return True + + elif globvar_AFMdata.channel[image_nr] == "df": + if not globvar_AFMdata.channel[image_nr] == "filtered": + if direction == "forward" and globvar_ThumbPara.thumbs[2]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[3]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Dissipation": + if direction == "forward" and globvar_ThumbPara.thumbs[4]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[5]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Amplitude": + if direction == "forward" and globvar_ThumbPara.thumbs[6]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[7]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin": + if not globvar_AFMdata.channel[image_nr] == "Error": + if direction == "forward" and globvar_ThumbPara.thumbs[8]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[9]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin Error": + if direction == "forward" and globvar_ThumbPara.thumbs[10]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[11]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 1": + if direction == "forward" and globvar_ThumbPara.thumbs[12]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[13]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 2": + if direction == "forward" and globvar_ThumbPara.thumbs[14]: + return True + elif direction == "backward" and globvar_ThumbPara.thumbs[15]: + return True + + else: + for i, chan in enumerate(globvar_ThumbPara.channel_names): + if not chan == "": + if re.search(chan,globvar_AFMdata.channel[image_nr]): + if direction == "forward" and \ + globvar_ThumbPara.thumbs[2*i+16]: + return True + elif direction == "backward" and \ + globvar_ThumbPara.thumbs[2*i+17]: + return True + + return False + + +def line_fit(image_nr,direction): + + if globvar_AFMdata.channel[image_nr] == "Topography": + if direction == "forward" and globvar_ThumbPara.line_fit[0]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[1]: + return True + + elif globvar_AFMdata.channel[image_nr] == "df": + if direction == "forward" and globvar_ThumbPara.line_fit[2]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[3]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Dissipation": + if direction == "forward" and globvar_ThumbPara.line_fit[4]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[5]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Amplitude": + if direction == "forward" and globvar_ThumbPara.line_fit[6]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[7]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin": + if direction == "forward" and globvar_ThumbPara.line_fit[8]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[9]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin Error": + if direction == "forward" and globvar_ThumbPara.line_fit[10]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[11]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 1": + if direction == "forward" and globvar_ThumbPara.line_fit[12]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[13]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 2": + if direction == "forward" and globvar_ThumbPara.line_fit[14]: + return True + elif direction == "backward" and globvar_ThumbPara.line_fit[15]: + return True + + else: + for i, chan in enumerate(globvar_ThumbPara.channel_names): + if not chan == "": + if re.search(chan,globvar_AFMdata.channel[image_nr]): + if direction == "forward" and \ + globvar_ThumbPara.line_fit[2*i+16]: + return True + elif direction == "backward" and \ + globvar_ThumbPara.line_fit[2*i+17]: + return True + + return False + + +def plane_fit(image_nr,direction): + + if globvar_AFMdata.channel[image_nr] == "Topography": + if direction == "forward" and globvar_ThumbPara.plane_fit[0]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[1]: + return True + + elif globvar_AFMdata.channel[image_nr] == "df": + if direction == "forward" and globvar_ThumbPara.plane_fit[2]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[3]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Dissipation": + if direction == "forward" and globvar_ThumbPara.plane_fit[4]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[5]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Amplitude": + if direction == "forward" and globvar_ThumbPara.plane_fit[6]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[7]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin": + if direction == "forward" and globvar_ThumbPara.plane_fit[8]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[9]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin Error": + if direction == "forward" and globvar_ThumbPara.plane_fit[10]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[11]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 1": + if direction == "forward" and globvar_ThumbPara.plane_fit[12]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[13]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 2": + if direction == "forward" and globvar_ThumbPara.plane_fit[14]: + return True + if direction == "backward" and globvar_ThumbPara.plane_fit[15]: + return True + + else: + for i, chan in enumerate(globvar_ThumbPara.channel_names): + if not chan == "": + if re.search(chan,globvar_AFMdata.channel[image_nr]): + if direction == "forward" and \ + globvar_ThumbPara.plane_fit[2*i+16]: + return True + elif direction == "backward" and \ + globvar_ThumbPara.plane_fit[2*i+17]: + return True + + return False + + +def invert(image_nr,direction): + + if not (direction == "forward" or direction == "backward"): + if image_nr%2 == 0: + direction = "forward" + elif image_nr%2 != 0: + direction = "backward" + + if globvar_AFMdata.channel[image_nr] == "Topography": + if direction == "forward" and globvar_ThumbPara.invert[0]: + return True + if direction == "backward" and globvar_ThumbPara.invert[1]: + return True + + elif globvar_AFMdata.channel[image_nr] == "df": + if direction == "forward" and globvar_ThumbPara.invert[2]: + return True + if direction == "backward" and globvar_ThumbPara.invert[3]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Dissipation": + if direction == "forward" and globvar_ThumbPara.invert[4]: + return True + if direction == "backward" and globvar_ThumbPara.invert[5]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Amplitude": + if direction == "forward" and globvar_ThumbPara.invert[6]: + return True + if direction == "backward" and globvar_ThumbPara.invert[7]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin": + if direction == "forward" and globvar_ThumbPara.invert[8]: + return True + if direction == "backward" and globvar_ThumbPara.invert[9]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Kelvin Error": + if direction == "forward" and globvar_ThumbPara.invert[10]: + return True + if direction == "backward" and globvar_ThumbPara.invert[11]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 1": + if direction == "forward" and globvar_ThumbPara.invert[12]: + return True + if direction == "backward" and globvar_ThumbPara.invert[13]: + return True + + elif globvar_AFMdata.channel[image_nr] == "Ext 2": + if direction == "forward" and globvar_ThumbPara.invert[14]: + return True + if direction == "backward" and globvar_ThumbPara.invert[15]: + return True + + else: + for i, chan in enumerate(globvar_ThumbPara.channel_names): + if not chan == "": + if re.search(chan,globvar_AFMdata.channel[image_nr]): + if direction == "forward" and \ + globvar_ThumbPara.invert[2*i+16]: + return True + elif direction == "backward" and \ + globvar_ThumbPara.invert[2*i+17]: + return True + + return False + + +def define_color(color): + + if color in globvar_color_dict: + return globvar_color_dict[color] + + else: + return globvar_color_dict["Grey"] + + +def select_color(image_nr,direction): + + if not (direction == "forward" or direction == "backward"): + if image_nr%2 == 0: + direction = "forward" + elif image_nr%2 != 0: + direction = "backward" + + if globvar_AFMdata.channel[image_nr] == "Topography": + if direction == "forward": + return globvar_ThumbPara.colors[0] + if direction == "backward": + return globvar_ThumbPara.colors[1] + + elif globvar_AFMdata.channel[image_nr] == "df": + if direction == "forward": + return globvar_ThumbPara.colors[2] + if direction == "backward": + return globvar_ThumbPara.colors[3] + + elif globvar_AFMdata.channel[image_nr] == "Dissipation": + if direction == "forward": + return globvar_ThumbPara.colors[4] + if direction == "backward": + return globvar_ThumbPara.colors[5] + + elif globvar_AFMdata.channel[image_nr] == "Amplitude": + if direction == "forward": + return globvar_ThumbPara.colors[6] + if direction == "backward": + return globvar_ThumbPara.colors[7] + + elif globvar_AFMdata.channel[image_nr] == "Kelvin": + if direction == "forward": + return globvar_ThumbPara.colors[8] + if direction == "backward": + return globvar_ThumbPara.colors[9] + + elif globvar_AFMdata.channel[image_nr] == "Kelvin Error": + if direction == "forward": + return globvar_ThumbPara.colors[10] + if direction == "backward": + return globvar_ThumbPara.colors[11] + + elif globvar_AFMdata.channel[image_nr] == "Ext 1": + if direction == "forward": + return globvar_ThumbPara.colors[12] + if direction == "backward": + return globvar_ThumbPara.colors[13] + + elif globvar_AFMdata.channel[image_nr] == "Ext 2": + if direction == "forward": + return globvar_ThumbPara.colors[14] + if direction == "backward": + return globvar_ThumbPara.colors[15] + + else: + for i, chan in enumerate(globvar_ThumbPara.channel_names): + if not chan == "": + if re.search(chan,globvar_AFMdata.channel[image_nr]): + if direction == "forward": + return globvar_ThumbPara.colors[2*i+16] + elif direction == "backward": + return globvar_ThumbPara.colors[2*i+17] + + return False diff --git a/AFM_thumbs/Channel.pyc b/AFM_thumbs/Channel.pyc new file mode 100755 index 0000000000000000000000000000000000000000..662a2d7bad444d3e19b1036236184f9514ac9376 GIT binary patch literal 8447 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/Colour.py b/AFM_thumbs/Colour.py new file mode 100755 index 0000000..80ab002 --- /dev/null +++ b/AFM_thumbs/Colour.py @@ -0,0 +1,145 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import sys +import os +import numpy as np + +# The following is a bit confusing but needed for crontab and ssh under Linux: +# Matplotlib needs an X-Server, which does not exist when doing, e.g., ssh. +# In the following we ask if the DISPLAY variable of the Linux system is set. +# If this is not the case then we tell Python to do something special for +# matplotlib (use of 'Agg') +# +# From: "http://stackoverflow.com/questions/4931376/ +# generating-matplotlib-graphs-without-a-running-x-server" +# Other solution: matplotlib API, see "http://www.dalkescientific.com/writings/ +# diary/archive/2005/04/23/matplotlib_without_gui.html" +if sys.platform == "linux2": + environ = os.environ + if "DISPLAY" not in environ: + import matplotlib as mpl + mpl.use('Agg') + # This is a one time message, which is not included in thumbs.py + # Otherwise it is reproduced 2 times. + print("\n\n**** ATTENTION!\n" + + "**** No X-Server is detected under Linux. It seems that\n" + + "**** AFM_thumbs is executed via ssh or crontab ... no problem.\n\n") +import matplotlib.pyplot as plt +from matplotlib.colors import LinearSegmentedColormap + +from AFM_thumbs.Variables import Color_list +from AFM_thumbs.Variables import globvar_color_options + +def plot_color_gradients(): + + # Get the lenght of the colour list + nrows = len(Color_list) + # Gradients + gradient = np.linspace(0, 1, 256) + gradient = np.vstack((gradient, gradient)) + + fig, axes = plt.subplots(nrows=nrows) + fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99) + axes[0].set_title("Color maps", fontsize=14) + + # Go through all colours. + for ax, colour, colourname in zip(axes, Color_list, globvar_color_options): + + # What kind of color scale do we have? + # Is it a pre-definied color from matplotlib, then it must be a string. + if type(colour) is str: + colormap = colour + # If it is not a string, then it must be a color definied by ourselves, + # so go to here and transform this linear segment into a colormap. + else: + colormap = LinearSegmentedColormap("Colormap",colour) + + # Prepare the plot + ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(colormap)) + pos = list(ax.get_position().bounds) + x_text = pos[0] - 0.01 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, colourname, + va='center', ha='right', fontsize=10) + + # Turn off *all* ticks & spines, not just the ones with colormaps. + for ax in axes: + ax.set_axis_off() + + # Show the plot. + plt.show() + + +# This definition was taken from +# http://stackoverflow.com/questions/3279560/invert-colormap-in-matplotlib +# User Mattijn +def reverse_colourmap(ctype, cmap, name = 'my_cmap_r'): + """ + In: + cmap, name + Out: + my_cmap_r + + Explanation: + t[0] goes from 0 to 1 + row i: x y0 y1 -> t[0] t[1] t[2] + / + / + row i+1: x y0 y1 -> t[n] t[1] t[2] + + so the inverse should do the same: + row i+1: x y1 y0 -> 1-t[0] t[2] t[1] + / + / + row i: x y1 y0 -> 1-t[n] t[2] t[1] + """ + + if ctype == "LinearSegmentedColormap": + + reverse = [] + k = [] + + for key in cmap._segmentdata: + k.append(key) + channel = cmap._segmentdata[key] + data = [] + + for t in channel: + data.append((1-t[0],t[2],t[1])) + reverse.append(sorted(data)) + + LinearL = dict(zip(k,reverse)) + my_cmap_r = LinearSegmentedColormap(name, LinearL) + + elif ctype == "ListedColormap": + + if cmap[-2:] == "_r": + my_cmap_r = cmap[:-2] + else: + my_cmap_r = cmap + "_r" + + return my_cmap_r diff --git a/AFM_thumbs/Colour.pyc b/AFM_thumbs/Colour.pyc new file mode 100755 index 0000000000000000000000000000000000000000..f58aad762c6b18b8e123f9e846bbb42ba84b63f8 GIT binary patch literal 3022 zcmb_ePj4H?6@Rm&NQo9jS(YrR1=^_&fsn+KWfVng6tM*>New7+K^bw&L?xEoA+^;0 z)6T3yIV4a({u0d>=q>jia?2$^`yqPiu?dhvZfSq-tzpPMu7hMza)D=|YhTz*nQypiZmr{^8V7^3u*6jT+RsA)>Ps%~RZ@P7@N~ zn4@Tc;udvU<-8&DMd~bKeuG}X-AG&U8KxK(tpVf_5i3}cf(`cWFCdF*E;Ljw##=|-V-C2a+? zVU+gH{Jh&|?rxg7Fiork{svb0d4$LQ6;>SniX$||z@t%xj}S3NP%kPpRYI)NMDc&% z2`7j%G^%lECqx&dKJ;jce}yK{P^U812z7w)&r#4I#0pWmpsJdPfpt!dCIt%=w4hR{ z@xRE;5f}L5Pk*4thu&lo^bYJpIT@rn)p64y66}fn;tZ z-YjymZi`+PrOvt*1g|DtKNuC(Azwf8^0d?+Af7WM^dmfDbOMkIPEs@;|<&A4P@v;H`=-E=UJ6;`^*h1F)nDb?qG z5aK+;ysooJ*Aczj{!^l|c z^SgL<^qse~@VgIojxf4+B#i9HD{cD+h$T%lzOi%v`x+BgcBN6IZHoKQ=rFyJwH%SJoEivu~hLi$0%)VVO1Hzb5LQoFd{1x?mE&*3t z-U@8}8Wp$R_w&%lXPA}CO0JXkU9hwnU$0O0r^H+agx|+$P( command line, no GUI + if options.directory is not None: + + # Does the working directory exist? If not => exit! + if not os.path.isdir(options.directory): + print("Usage: AFM_thumbs.py [options]\n\n" \ + "AFM_thumbs.py: error: working directory does not exist!") + exit(-1) + + # ............. Start without GUI + config_file = initialize_check_config(options.configfile) + read_configfile(config_file) + + # Does a special pdf path exist? + if options.pdf is not None: + if os.path.isdir(options.pdf): + globvar_AFMdir.pdf_path = options.pdf + # Strange, the directory does not exist! Error and exit. + else: + print("Usage: AFM_thumbs.py [options]\n\n" \ + "AFM_thumbs.py: error: The pdf directory " + + "'" + options.pdf + "' does not exist !") + exit(-1) + + return (False, options.directory, config_file) + + # If no options are set and there is nothing in args: start the GUI + elif options.directory == None and \ + options.pdf == None and \ + options.configfile == None and \ + args == []: + return (True, None, None) + + # -p option but where is the -d option? + elif options.pdf is not None: + print("Usage: AFM_thumbs.py [options]\n\n" \ + "AFM_thumbs.py: error: working directory ?") + exit(-1) + + # -c option but where is the -d option? + elif options.configfile is not None: + print("Usage: AFM_thumbs.py [options]\n\n" \ + "AFM_thumbs.py: error: working directory ?") + exit(-1) + + # All other: exit. + else: + print("Usage: AFM_thumbs.py [options]\n\n" \ + "AFM_thumbs.py: error: options ?") + exit(-1) + + +def read_configfile(filepath_config): + + # From here on, the parameters from the config file are stored into + # the variables. + # filepath_config = os.path.join(globvar_configfile_path, + # globvar_configfile) + + config_file_p = open(filepath_config, "r") + + # This has to be modified ... + for line in config_file_p: + if "PDF Path:" in line: + globvar_AFMdir.pdf_path = "" + break + + # Go to parameters. + for line in config_file_p: + if "Parameters" in line: + break + + # The whole config file is read + for line in config_file_p: + + if "Channelname " in line: + break + + if "Rows" in line: + globvar_ThumbPara.row = int(line[25:-1]) + if "Columns" in line: + globvar_ThumbPara.col = int(line[25:-1]) + if "Rms" in line: + globvar_ThumbPara.rms = line[25:-1] + if "Image resolution" in line: + globvar_ThumbPara.res = line[25:-1] + if "Jpeg quality" in line: + globvar_ThumbPara.jpeg = line[25:-1] + if "X text position" in line: + globvar_ThumbPara.text_x = line[25:-1] + if "Y text position" in line: + globvar_ThumbPara.text_y = line[25:-1] + if "Text size" in line: + globvar_ThumbPara.text_size = line[25:-1] + if "Dx of text" in line: + globvar_ThumbPara.text_block = line[25:-1] + if "Font" in line: + font_list = get_fonts() + if line[25:-1] in font_list: + globvar_ThumbPara.font = line[25:-1] + else: + # If the font is not available then take the first of the + # list of available preferred fonts. + globvar_ThumbPara.font = font_list[0] + if "Deleting thumbs before" in line: + globvar_ThumbPara.thumbs_before = bool(int(line[25:-1])) + if "Deleting thumbs after" in line: + globvar_ThumbPara.thumbs_after = bool(int(line[25:-1])) + if "Spektral Options" in line: + globvar_ThumbPara.spektra = bool(int(line[25:-1])) + if "Peek Options" in line: + globvar_ThumbPara.peek = bool(int(line[25:-1])) + if "Format Options" in line: + globvar_ThumbPara.png = bool(int(line[25:-1])) + if "Date" in line: + globvar_ThumbPara.date = bool(int(line[25:-1])) + if "Size in nm" in line: + globvar_ThumbPara.sizenm = bool(int(line[25:-1])) + if "Size in px" in line: + globvar_ThumbPara.sizepx = bool(int(line[25:-1])) + if "Offset" in line: + globvar_ThumbPara.offset = bool(int(line[25:-1])) + if "Voltage" in line: + globvar_ThumbPara.voltage = bool(int(line[25:-1])) + if "Feedback" in line: + globvar_ThumbPara.feedback = bool(int(line[25:-1])) + if "Gain" in line: + globvar_ThumbPara.gain = bool(int(line[25:-1])) + if "Speed" in line: + globvar_ThumbPara.speed = bool(int(line[25:-1])) + if "Amplitude" in line: + globvar_ThumbPara.ampl = bool(int(line[25:-1])) + if "Angle" in line: + globvar_ThumbPara.angle = bool(int(line[25:-1])) + if "Extra directories" in line: + globvar_ThumbPara.extra_direct = bool(int(line[25:-1])) + if "Subdirs" in line: + globvar_ThumbPara.subdirs = bool(int(line[25:-1])) + if "File extension" in line: + globvar_ThumbPara.extension = line[25:-1] + if "Master directory" in line: + globvar_ThumbPara.masterdir = line[25:-1] + if "Filename" in line: + globvar_ThumbPara.filename = line[25:-1] + if "Replace pdfs" in line: + globvar_ThumbPara.pdfs = bool(int(line[25:-1])) + if "RHK Special Options" in line: + RHK_special.true = bool(int(line[25:-1])) + + # Read now the channels: + config_file_p.seek(0, 0) + for line in config_file_p: + if "Tooltips" in line: + break + for line in config_file_p: + if "Channelname " in line: + globvar_ThumbPara.channel_names.append(line[25:-1]) + + # Read now the thumb bools: + config_file_p.seek(0, 0) + for line in config_file_p: + if "Tooltips" in line: + break + for line in config_file_p: + if "Thumb " in line: + globvar_ThumbPara.thumbs.append(bool(int(line[25:-1]))) + + # Read now the line_fit bools: + config_file_p.seek(0, 0) + for line in config_file_p: + if "Tooltips" in line: + break + for line in config_file_p: + if "LineFit " in line: + globvar_ThumbPara.line_fit.append(bool(int(line[25:-1]))) + + # Read now the plane_fit bools: + config_file_p.seek(0, 0) + for line in config_file_p: + if "Tooltips" in line: + break + for line in config_file_p: + if "PlaneFit " in line: + globvar_ThumbPara.plane_fit.append(bool(int(line[25:-1]))) + + # Read now the inverted bools: + config_file_p.seek(0, 0) + for line in config_file_p: + if "Tooltips" in line: + break + for line in config_file_p: + if "Inverted " in line: + globvar_ThumbPara.invert.append(bool(int(line[25:-1]))) + + # Read now the colors: + config_file_p.seek(0, 0) + for line in config_file_p: + if "Tooltips" in line: + break + for line in config_file_p: + if "Color " in line: + globvar_ThumbPara.colors.append(define_color(line[25:-1])) + + globvar_ThumbPara.geometry_x.append(globvar_thumb_size_x * \ + float(globvar_ThumbPara.res)) + globvar_ThumbPara.geometry_y.append(globvar_thumb_size_y * \ + float(globvar_ThumbPara.res)) + + config_file_p.close() + + +# This definition clarifies, which fonts are available on the system and which +# of the preferred fonts in 'globvar_fonts' is in the list of available_fonts. +# Return the list of available preferred fonts. +# In the variable 'globvar_bad_fonts' one finds the bad fonts (e.g., NotoColorEmoji), +# which are excluded here! +def get_fonts(): + + font_list = [] + + all_fonts_with_path = matplotlib.font_manager.get_fontconfig_fonts() + all_fonts = [] + for fname in all_fonts_with_path: + if str(os.path.basename(fname)) in globvar_bad_fonts: + continue + tmp = matplotlib.font_manager.FontProperties(fname=fname).get_name() + all_fonts.append(tmp) + + for font in globvar_fonts: + if font in all_fonts: + font_list.append(font) + + return font_list diff --git a/AFM_thumbs/Command_line.pyc b/AFM_thumbs/Command_line.pyc new file mode 100755 index 0000000000000000000000000000000000000000..f60073cf3ae0ccdd6b33521f110382f1ed81d55b GIT binary patch literal 7086 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

i$WBgq@RD0nGYv(YsBj9<&tkLLc zLdmDD;8nlFX9uAaW|33F4bIgfQA>@c=v4G^X>-mMF)t1|&e!VXE6zQ5I9-UYi#A^{ zyIhdDH8?>lj7E`THI9fI2u`z{wFP>+gUi!6g6pTn9bDjgceoEYOAREF)^v;dK;YR% zRK8iJw8#zZjO6!aO6Rdh;yh>tQ4;u7UV`jSNG)K4kCS;CVs~@V8ItZkLpvH0m-Y$# z+9!z>t-`8{bRC%6L`I-V=S`Sw#Mm3-g!Xs>5kCewsMw@dnapYj_$0JtBRQv~IJbPP z0#3frF4t?fn*?PU&6fQ-D*q?fUjyrN*hthd6oi@QG|Hs0gjC8&xCA-dyjdnAX+t2< zpbdc}5T}H6_KE=gEY8Y1ZtS~NoP)eau?5&*d{*cqgbhObgH0Ao=;R+@aIN>>9GuBY zDE~D;?%sEJN3x$KCbWcY8cg3#T>45gP^9U1nvu63$nTOzD3Uq>6U~@2#zTLZ;@idF F{tr{s8cYBH literal 0 HcmV?d00001 diff --git a/AFM_thumbs/Config_AFM_thumbs.conf b/AFM_thumbs/Config_AFM_thumbs.conf new file mode 100644 index 0000000..12a43c0 --- /dev/null +++ b/AFM_thumbs/Config_AFM_thumbs.conf @@ -0,0 +1,166 @@ +# +# +# This is the config file of the 'Advanced SCALA contact sheets' tool +# +# Don't make any changes +# + + +Last directory: /media/cle/Daten/Data/X -- 2022/Programming/Python_AFM_thumbs/AFM_thumbs/Aktuelle_version_python3/TESTS +PDF Path: + + +Parameters +========== +Rows : 6 +Columns : 4 +Rms : 2.5 +Image resolution : 100 +Jpeg quality : 40 +X text position : 0 +Y text position : 0 +Text size : 13 +Dx of text : 0 +Font : Arial +Date : 1 +Size in nm : 1 +Size in px : 1 +Offset : 1 +Voltage : 1 +Feedback : 1 +Gain : 1 +Speed : 1 +Amplitude : 1 +Angle : 1 +Deleting thumbs before : 0 +Deleting thumbs after : 0 +Extra directories : 0 +Replace pdfs : 0 +Subdirs : 1 +Spektral Options : 1 +Format Options : 1 +Peek Options : 0 +Minimum on zero Options: 0 +Master directory : +Filename : +Color : ReiGreen +File extension : +Direction : 0 +Linefit : 0 +Planefit : 3 +AddChannel : 17 +ChannelNumber : 3 +Tooltips : 0 +Channelname 1 : FN +Channelname 2 : FL +Channelname 3 : I +Thumb 1 : 1 +Thumb 2 : 1 +Thumb 3 : 1 +Thumb 4 : 1 +Thumb 5 : 1 +Thumb 6 : 1 +Thumb 7 : 1 +Thumb 8 : 1 +Thumb 9 : 1 +Thumb 10 : 1 +Thumb 11 : 1 +Thumb 12 : 1 +Thumb 13 : 1 +Thumb 14 : 1 +Thumb 15 : 1 +Thumb 16 : 1 +Thumb 17 : 1 +Thumb 18 : 1 +Thumb 19 : 1 +Thumb 20 : 1 +Thumb 21 : 1 +Thumb 22 : 1 +LineFit 1 : 1 +LineFit 2 : 1 +LineFit 3 : 1 +LineFit 4 : 1 +LineFit 5 : 1 +LineFit 6 : 1 +LineFit 7 : 1 +LineFit 8 : 1 +LineFit 9 : 1 +LineFit 10 : 1 +LineFit 11 : 1 +LineFit 12 : 1 +LineFit 13 : 1 +LineFit 14 : 1 +LineFit 15 : 1 +LineFit 16 : 1 +LineFit 17 : 1 +LineFit 18 : 1 +LineFit 19 : 1 +LineFit 20 : 1 +LineFit 21 : 1 +LineFit 22 : 1 +PlaneFit 1 : 0 +PlaneFit 2 : 0 +PlaneFit 3 : 0 +PlaneFit 4 : 0 +PlaneFit 5 : 0 +PlaneFit 6 : 0 +PlaneFit 7 : 0 +PlaneFit 8 : 0 +PlaneFit 9 : 0 +PlaneFit 10 : 0 +PlaneFit 11 : 0 +PlaneFit 12 : 0 +PlaneFit 13 : 0 +PlaneFit 14 : 0 +PlaneFit 15 : 0 +PlaneFit 16 : 0 +PlaneFit 17 : 0 +PlaneFit 18 : 0 +PlaneFit 19 : 0 +PlaneFit 20 : 0 +PlaneFit 21 : 0 +PlaneFit 22 : 0 +Inverted 1 : 0 +Inverted 2 : 0 +Inverted 3 : 1 +Inverted 4 : 1 +Inverted 5 : 0 +Inverted 6 : 0 +Inverted 7 : 0 +Inverted 8 : 0 +Inverted 9 : 0 +Inverted 10 : 0 +Inverted 11 : 0 +Inverted 12 : 0 +Inverted 13 : 1 +Inverted 14 : 1 +Inverted 15 : 0 +Inverted 16 : 0 +Inverted 17 : 0 +Inverted 18 : 0 +Inverted 19 : 0 +Inverted 20 : 0 +Inverted 21 : 0 +Inverted 22 : 0 +Color 1 : AFMhot +Color 2 : AFMhot +Color 3 : Grey +Color 4 : Grey +Color 5 : Yellow +Color 6 : Yellow +Color 7 : Grey +Color 8 : Grey +Color 9 : ReiGreen +Color 10 : ReiGreen +Color 11 : Red +Color 12 : Red +Color 13 : Blue2 +Color 14 : Blue2 +Color 15 : ReiGreen +Color 16 : ReiGreen +Color 17 : Blue2 +Color 18 : Blue2 +Color 19 : Blue +Color 20 : Blue +Color 21 : Ocean +Color 22 : Ocean diff --git a/AFM_thumbs/Config_AFM_thumbs.conf~ b/AFM_thumbs/Config_AFM_thumbs.conf~ new file mode 100755 index 0000000..cf3617a --- /dev/null +++ b/AFM_thumbs/Config_AFM_thumbs.conf~ @@ -0,0 +1,166 @@ +# +# +# This is the config file of the 'Advanced SCALA contact sheets' tool +# +# Don't make any changes +# + + +Last directory: /media/cle/Daten/Data/X -- 2012/rawdata/sample_Brice/NaCl_C60_01june2012p2 +PDF Path: + + +Parameters +========== +Rows : 6 +Columns : 4 +Rms : 1.3 +Image resolution : 100 +Jpeg quality : 40 +X text position : 0 +Y text position : 0 +Text size : 13 +Dx of text : 0 +Font : FreeSans +Date : 1 +Size in nm : 1 +Size in px : 1 +Offset : 1 +Voltage : 1 +Feedback : 1 +Gain : 1 +Speed : 1 +Amplitude : 1 +Angle : 1 +Deleting thumbs before : 0 +Deleting thumbs after : 0 +Extra directories : 0 +Replace pdfs : 1 +Subdirs : 1 +Spektral Options : 1 +Format Options : 0 +Peek Options : 0 +Minimum on zero Options: 0 +Master directory : +Filename : +Color : ReiGreen +File extension : _noline +Direction : 0 +Linefit : 3 +Planefit : 3 +AddChannel : 17 +ChannelNumber : 3 +Tooltips : 0 +Channelname 1 : FN +Channelname 2 : FL +Channelname 3 : I +Thumb 1 : 1 +Thumb 2 : 1 +Thumb 3 : 1 +Thumb 4 : 1 +Thumb 5 : 1 +Thumb 6 : 1 +Thumb 7 : 1 +Thumb 8 : 1 +Thumb 9 : 1 +Thumb 10 : 1 +Thumb 11 : 1 +Thumb 12 : 1 +Thumb 13 : 1 +Thumb 14 : 1 +Thumb 15 : 1 +Thumb 16 : 1 +Thumb 17 : 1 +Thumb 18 : 1 +Thumb 19 : 1 +Thumb 20 : 1 +Thumb 21 : 1 +Thumb 22 : 1 +LineFit 1 : 0 +LineFit 2 : 0 +LineFit 3 : 0 +LineFit 4 : 0 +LineFit 5 : 0 +LineFit 6 : 0 +LineFit 7 : 0 +LineFit 8 : 0 +LineFit 9 : 0 +LineFit 10 : 0 +LineFit 11 : 0 +LineFit 12 : 0 +LineFit 13 : 0 +LineFit 14 : 0 +LineFit 15 : 0 +LineFit 16 : 0 +LineFit 17 : 0 +LineFit 18 : 0 +LineFit 19 : 0 +LineFit 20 : 0 +LineFit 21 : 0 +LineFit 22 : 0 +PlaneFit 1 : 0 +PlaneFit 2 : 0 +PlaneFit 3 : 0 +PlaneFit 4 : 0 +PlaneFit 5 : 0 +PlaneFit 6 : 0 +PlaneFit 7 : 0 +PlaneFit 8 : 0 +PlaneFit 9 : 0 +PlaneFit 10 : 0 +PlaneFit 11 : 0 +PlaneFit 12 : 0 +PlaneFit 13 : 0 +PlaneFit 14 : 0 +PlaneFit 15 : 0 +PlaneFit 16 : 0 +PlaneFit 17 : 0 +PlaneFit 18 : 0 +PlaneFit 19 : 0 +PlaneFit 20 : 0 +PlaneFit 21 : 0 +PlaneFit 22 : 0 +Inverted 1 : 1 +Inverted 2 : 1 +Inverted 3 : 1 +Inverted 4 : 1 +Inverted 5 : 1 +Inverted 6 : 1 +Inverted 7 : 1 +Inverted 8 : 1 +Inverted 9 : 1 +Inverted 10 : 1 +Inverted 11 : 1 +Inverted 12 : 1 +Inverted 13 : 1 +Inverted 14 : 1 +Inverted 15 : 1 +Inverted 16 : 1 +Inverted 17 : 1 +Inverted 18 : 1 +Inverted 19 : 1 +Inverted 20 : 1 +Inverted 21 : 1 +Inverted 22 : 1 +Color 1 : BluePurple +Color 2 : PurpleBlue +Color 3 : Grey +Color 4 : Grey +Color 5 : PupleRed +Color 6 : RedPurple +Color 7 : Grey +Color 8 : Grey +Color 9 : OrangeRed +Color 10 : PurpleBlueGreen +Color 11 : Red +Color 12 : Red +Color 13 : Gnuplot +Color 14 : Gnuplot2 +Color 15 : ReiGreen +Color 16 : ReiGreen +Color 17 : Blue2 +Color 18 : Blue2 +Color 19 : Blue +Color 20 : Blue +Color 21 : Ocean +Color 22 : Ocean diff --git a/AFM_thumbs/Config_default.conf b/AFM_thumbs/Config_default.conf new file mode 100644 index 0000000..80731b1 --- /dev/null +++ b/AFM_thumbs/Config_default.conf @@ -0,0 +1,177 @@ +# +# +# This is the config file of the 'Advanced SCALA contact sheets' tool +# +# Don't make any changes +# + + +Last directory: /media/cle/Daten/Data/X -- 2021/rawdata/NANONIS +PDF Path: + + +Parameters +========== +Rows : 6 +Columns : 4 +Rms : 1.3 +Image resolution : 100 +Jpeg quality : 40 +X text position : 0 +Y text position : 0 +Text size : 13 +Dx of text : 0 +Font : FreeSans +Date : 1 +Size in nm : 1 +Size in px : 1 +Offset : 1 +Voltage : 1 +Feedback : 1 +Gain : 1 +Speed : 1 +Amplitude : 1 +Angle : 1 +Deleting thumbs before : 0 +Deleting thumbs after : 0 +Extra directories : 0 +Replace pdfs : 0 +Subdirs : 1 +Spektral Options : 1 +Format Options : 0 +Peek Options : 0 +Minimum on zero Options: 0 +Master directory : +Filename : +Color : ReiGreen +File extension : +Direction : 0 +Linefit : 3 +Planefit : 3 +AddChannel : 20 +ChannelNumber : 4 +Tooltips : 0 +Channelname 1 : FN +Channelname 2 : FL +Channelname 3 : I +Channelname 4 : Phase +Thumb 1 : 1 +Thumb 2 : 1 +Thumb 3 : 1 +Thumb 4 : 1 +Thumb 5 : 1 +Thumb 6 : 1 +Thumb 7 : 1 +Thumb 8 : 1 +Thumb 9 : 1 +Thumb 10 : 1 +Thumb 11 : 1 +Thumb 12 : 1 +Thumb 13 : 1 +Thumb 14 : 1 +Thumb 15 : 1 +Thumb 16 : 1 +Thumb 17 : 1 +Thumb 18 : 1 +Thumb 19 : 1 +Thumb 20 : 1 +Thumb 21 : 1 +Thumb 22 : 1 +Thumb 23 : 1 +Thumb 24 : 1 +LineFit 1 : 1 +LineFit 2 : 1 +LineFit 3 : 1 +LineFit 4 : 1 +LineFit 5 : 1 +LineFit 6 : 1 +LineFit 7 : 1 +LineFit 8 : 1 +LineFit 9 : 1 +LineFit 10 : 1 +LineFit 11 : 1 +LineFit 12 : 1 +LineFit 13 : 1 +LineFit 14 : 1 +LineFit 15 : 1 +LineFit 16 : 1 +LineFit 17 : 1 +LineFit 18 : 1 +LineFit 19 : 1 +LineFit 20 : 1 +LineFit 21 : 1 +LineFit 22 : 1 +LineFit 23 : 1 +LineFit 24 : 1 +PlaneFit 1 : 0 +PlaneFit 2 : 0 +PlaneFit 3 : 0 +PlaneFit 4 : 0 +PlaneFit 5 : 0 +PlaneFit 6 : 0 +PlaneFit 7 : 0 +PlaneFit 8 : 0 +PlaneFit 9 : 0 +PlaneFit 10 : 0 +PlaneFit 11 : 0 +PlaneFit 12 : 0 +PlaneFit 13 : 0 +PlaneFit 14 : 0 +PlaneFit 15 : 0 +PlaneFit 16 : 0 +PlaneFit 17 : 0 +PlaneFit 18 : 0 +PlaneFit 19 : 0 +PlaneFit 20 : 0 +PlaneFit 21 : 0 +PlaneFit 22 : 0 +PlaneFit 23 : 0 +PlaneFit 24 : 0 +Inverted 1 : 0 +Inverted 2 : 0 +Inverted 3 : 1 +Inverted 4 : 1 +Inverted 5 : 0 +Inverted 6 : 0 +Inverted 7 : 0 +Inverted 8 : 0 +Inverted 9 : 0 +Inverted 10 : 0 +Inverted 11 : 0 +Inverted 12 : 0 +Inverted 13 : 1 +Inverted 14 : 1 +Inverted 15 : 0 +Inverted 16 : 0 +Inverted 17 : 0 +Inverted 18 : 0 +Inverted 19 : 0 +Inverted 20 : 0 +Inverted 21 : 0 +Inverted 22 : 0 +Inverted 23 : 0 +Inverted 24 : 0 +Color 1 : Gist_heat +Color 2 : Gist_heat +Color 3 : Grey +Color 4 : Grey +Color 5 : AFMhot +Color 6 : AFMhot +Color 7 : Grey +Color 8 : Grey +Color 9 : Grey +Color 10 : Grey +Color 11 : Red +Color 12 : Red +Color 13 : Blue2 +Color 14 : Blue2 +Color 15 : ReiGreen +Color 16 : ReiGreen +Color 17 : Blue2 +Color 18 : Blue2 +Color 19 : Blue +Color 20 : Blue +Color 21 : Ocean +Color 22 : Ocean +Color 23 : Grey +Color 24 : Grey diff --git a/AFM_thumbs/Config_default.conf~ b/AFM_thumbs/Config_default.conf~ new file mode 100755 index 0000000..f0036bf --- /dev/null +++ b/AFM_thumbs/Config_default.conf~ @@ -0,0 +1,166 @@ +# +# +# This is the config file of the 'Advanced SCALA contact sheets' tool +# +# Don't make any changes +# + + +Last directory: /media/cle/Daten/Data/X -- 2016/rawdata/sample_Pd-HOPG/Ceria_10ML_Pd_annealed_Ethylene_2016-01-03 +PDF Path: /media/cle/Daten/Data/X -- 2016/rawdata/sample_Pd-HOPG/Ficken + + +Parameters +========== +Rows : 6 +Columns : 4 +Rms : 1.3 +Image resolution : 100 +Jpeg quality : 40 +X text position : 0 +Y text position : 0 +Text size : 13 +Dx of text : 0 +Font : Arial +Date : 1 +Size in nm : 1 +Size in px : 1 +Offset : 1 +Voltage : 1 +Feedback : 1 +Gain : 1 +Speed : 1 +Amplitude : 1 +Angle : 1 +Deleting thumbs before : 0 +Deleting thumbs after : 0 +Extra directories : 0 +Replace pdfs : 1 +Subdirs : 0 +Spektral Options : 1 +Format Options : 0 +Peek Options : 0 +Minimum on zero Options: 0 +Master directory : +Filename : +Color : ReiGreen +File extension : _noline +Direction : 0 +Linefit : 3 +Planefit : 3 +AddChannel : 17 +ChannelNumber : 3 +Tooltips : 0 +Channelname 1 : FN +Channelname 2 : FL +Channelname 3 : I +Thumb 1 : 1 +Thumb 2 : 1 +Thumb 3 : 1 +Thumb 4 : 1 +Thumb 5 : 1 +Thumb 6 : 1 +Thumb 7 : 1 +Thumb 8 : 1 +Thumb 9 : 1 +Thumb 10 : 1 +Thumb 11 : 1 +Thumb 12 : 1 +Thumb 13 : 1 +Thumb 14 : 1 +Thumb 15 : 1 +Thumb 16 : 1 +Thumb 17 : 1 +Thumb 18 : 1 +Thumb 19 : 1 +Thumb 20 : 1 +Thumb 21 : 1 +Thumb 22 : 1 +LineFit 1 : 0 +LineFit 2 : 0 +LineFit 3 : 0 +LineFit 4 : 0 +LineFit 5 : 0 +LineFit 6 : 0 +LineFit 7 : 0 +LineFit 8 : 0 +LineFit 9 : 0 +LineFit 10 : 0 +LineFit 11 : 0 +LineFit 12 : 0 +LineFit 13 : 0 +LineFit 14 : 0 +LineFit 15 : 0 +LineFit 16 : 0 +LineFit 17 : 0 +LineFit 18 : 0 +LineFit 19 : 0 +LineFit 20 : 0 +LineFit 21 : 0 +LineFit 22 : 0 +PlaneFit 1 : 1 +PlaneFit 2 : 1 +PlaneFit 3 : 0 +PlaneFit 4 : 0 +PlaneFit 5 : 0 +PlaneFit 6 : 0 +PlaneFit 7 : 0 +PlaneFit 8 : 0 +PlaneFit 9 : 0 +PlaneFit 10 : 0 +PlaneFit 11 : 0 +PlaneFit 12 : 0 +PlaneFit 13 : 1 +PlaneFit 14 : 1 +PlaneFit 15 : 0 +PlaneFit 16 : 0 +PlaneFit 17 : 0 +PlaneFit 18 : 0 +PlaneFit 19 : 0 +PlaneFit 20 : 0 +PlaneFit 21 : 0 +PlaneFit 22 : 0 +Inverted 1 : 0 +Inverted 2 : 0 +Inverted 3 : 1 +Inverted 4 : 1 +Inverted 5 : 0 +Inverted 6 : 0 +Inverted 7 : 0 +Inverted 8 : 0 +Inverted 9 : 0 +Inverted 10 : 0 +Inverted 11 : 0 +Inverted 12 : 0 +Inverted 13 : 1 +Inverted 14 : 1 +Inverted 15 : 0 +Inverted 16 : 0 +Inverted 17 : 0 +Inverted 18 : 0 +Inverted 19 : 0 +Inverted 20 : 0 +Inverted 21 : 0 +Inverted 22 : 0 +Color 1 : Gist_heat +Color 2 : Gist_heat +Color 3 : Grey +Color 4 : Grey +Color 5 : AFMhot +Color 6 : AFMhot +Color 7 : Grey +Color 8 : Grey +Color 9 : Grey +Color 10 : Grey +Color 11 : Red +Color 12 : Red +Color 13 : Blue2 +Color 14 : Blue2 +Color 15 : ReiGreen +Color 16 : ReiGreen +Color 17 : Blue2 +Color 18 : Blue2 +Color 19 : Blue +Color 20 : Blue +Color 21 : Ocean +Color 22 : Ocean diff --git a/AFM_thumbs/Initialize.py b/AFM_thumbs/Initialize.py new file mode 100755 index 0000000..e30590d --- /dev/null +++ b/AFM_thumbs/Initialize.py @@ -0,0 +1,223 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import os +import shutil + +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_spaces +from AFM_thumbs.Variables import globvar_configfile_path +from AFM_thumbs.Variables import globvar_configfile +from AFM_thumbs.Variables import globvar_python_directory +from AFM_thumbs.Variables import globvar_default_config +from AFM_thumbs.Variables import RHK_PositionCounter + + +def initialize_position_counter(): + RHK_PositionCounter.position = 0 + + +def initialize_AFM_data(): + globvar_AFMdata.date = "" + globvar_AFMdata.x_size = "" + globvar_AFMdata.y_size = "" + globvar_AFMdata.x_pixel = "" + globvar_AFMdata.y_pixel = "" + globvar_AFMdata.x_off = "" + globvar_AFMdata.y_off = "" + globvar_AFMdata.voltage = "" + globvar_AFMdata.measurement_type = "" + globvar_AFMdata.feedback = "" + globvar_AFMdata.gain = "" + globvar_AFMdata.gain_prop = "" + globvar_AFMdata.gain_int = "" + globvar_AFMdata.gain_xy = "" + globvar_AFMdata.gain_signal = "" + globvar_AFMdata.gain_z = "" + globvar_AFMdata.speed = "" + globvar_AFMdata.res_freq = "" + globvar_AFMdata.amplitude = "" + globvar_AFMdata.angle = "" + globvar_AFMdata.scan_updown = "" + globvar_AFMdata.sweep_f0 = "" + globvar_AFMdata.sweep_phase = "" + globvar_AFMdata.sweep_A_exec = "" + globvar_AFMdata.sweep_Q = "" + globvar_AFMdata.NONE = "" + globvar_AFMdata.datfile[:] = [] + globvar_AFMdata.channel[:] = [] + globvar_AFMdata.unit[:] = [] + globvar_AFMdata.z_average = 0.0 + globvar_AFMdata.z_factor[:] = [] + globvar_AFMdata.z_offset[:] = [] + globvar_AFMdata.z_calibration[:] = [] + globvar_AFMdata.z_amplitude[:] = [] + globvar_AFMdata.z_min[:] = [] + globvar_AFMdata.z_max[:] = [] + globvar_AFMdata.scandir[:] = [] + globvar_AFMdata.spec_x_unit[:] = [] + globvar_AFMdata.spec_x_label[:] = [] + globvar_AFMdata.spec_y_unit[:] = [] + globvar_AFMdata.spec_y_label[:] = [] + globvar_AFMdata.spec_y_factor[:] = [] + globvar_AFMdata.spec_points[:] = [] + globvar_AFMdata.spec_feedback[:] = [] + globvar_AFMdata.spec_acquisition[:] = [] + globvar_AFMdata.spec_delay[:] = [] + globvar_AFMdata.spec_time[:] = [] + globvar_AFMdata.spec_position[:] = [] + globvar_AFMdata.spec_files[:] = [] + + +def initialize_dir(): + # If the user chooses 'Cancel' -> exit + if not globvar_AFMdir.working_directory: + return False + + # The pdfs shall not be replaced if 0 + if globvar_ThumbPara.pdfs == 0: + # There is no special path for the pdfs ... + if globvar_AFMdir.pdf_path == "": + # The name of the pdf that may exist + file_pdf = os.path.abspath(globvar_AFMdir.working_directory) + \ + globvar_ThumbPara.extension+".pdf" + + # ... there is a special path for the pdfs! + else: + # The name of the pdf that may exist + file_pdf = os.path.basename(globvar_AFMdir.working_directory) + \ + globvar_ThumbPara.extension + \ + ".pdf" + file_pdf = os.path.join(globvar_AFMdir.pdf_path, file_pdf) + + + # If the pdf does exist, then simply do nothing => return False! + if os.path.isfile(file_pdf): + print(globvar_spaces + "The pdf file\n" + + globvar_spaces + + "'" + file_pdf + "'\n" + + globvar_spaces + + "does already exist !\n") + return False + + + # Name of directory + globvar_AFMdir.data_directory_name = \ + os.path.basename(globvar_AFMdir.working_directory) + + # Thumbnail directory will be created in the working directory + globvar_AFMdir.thumbnail_directory = \ + os.path.join(globvar_AFMdir.working_directory, + "thumbnails" + globvar_ThumbPara.extension) + + # If some thumbnails are already existing but shall be deleted, then do ... + if globvar_ThumbPara.thumbs_before == True: + if os.path.isdir(globvar_AFMdir.thumbnail_directory): + delete_string = globvar_AFMdir.thumbnail_directory + shutil.rmtree(delete_string) +#============================================================================== +# delete_string = "rm -rf \""+globvar_AFMdir.thumbnail_directory+"\"" +# os.system(delete_string) +#============================================================================== + + + # Name of superior directory + superior_directory = os.path.dirname(globvar_AFMdir.working_directory) + + # Name of directory even above + if (len(superior_directory)-superior_directory.rfind(os.pathsep))>0: + superior_2_times_directory = os.path.dirname(superior_directory) + + if globvar_ThumbPara.extra_direct == True: + + # Create, if it doesn't exist, a directory 'WSxM' and 'Gwyddion', which + # are on the same level as 'sample'. + # This is for future work, where treated WSxM and Gwyddion files can + # hutil be stored in these directories and ... + directory_WSxM = os.path.join(superior_2_times_directory,"WSxM") + if not os.path.isdir(directory_WSxM): + os.mkdir(directory_WSxM) + + directory_Gwyddion = os.path.join(superior_2_times_directory, + "Gwyddion") + if not os.path.isdir(directory_Gwyddion): + os.mkdir(directory_Gwyddion) + + # ... in the respective sub directories + directory_WSxM_data = os.path.join(directory_WSxM, + globvar_AFMdir.data_directory_name) + if not os.path.isdir(directory_WSxM_data): + os.mkdir(directory_WSxM_data) + + directory_Gwyddion_data = os.path.join(directory_Gwyddion, + globvar_AFMdir.data_directory_name) + if not os.path.isdir(directory_Gwyddion_data): + os.mkdir(directory_Gwyddion_data) + + # Thumbnail directory in working directory + if not os.path.isdir(globvar_AFMdir.thumbnail_directory): + os.mkdir(globvar_AFMdir.thumbnail_directory) + + return True + + +# Determine the config file. +def initialize_check_config(file_config): + + if file_config == None: + file_config = os.path.join(globvar_configfile_path,globvar_configfile) + + path_rel_default_config = os.path.join(globvar_python_directory, + globvar_default_config) + + if not os.path.isfile(file_config): + print(globvar_spaces + "Attention: The config file\n" + + globvar_spaces + file_config + "\n" + globvar_spaces + + "does not exist!\n" + globvar_spaces + + "The default config file '" + + path_rel_default_config + + "' " + + "is now used!\n" + globvar_spaces + + "If you have your own config file, put in the correct " + + "file name and path\n" + globvar_spaces + + "in 'AFM_thumbs/Variables.py' => " + + "'globvar_configfile' and 'globvar_configfile_path'\n") + + filepath_program = os.path.realpath(__file__) + path_program = os.path.dirname(filepath_program) + file_config = os.path.join(path_program,globvar_default_config) + + if not os.path.isfile(file_config): + print(globvar_spaces + + "Attention, MAJOR ERROR !!! The default config file\n" + + globvar_spaces + file_config + "\n" + globvar_spaces + + "does not exist! Re-install the whole program.\n" + + globvar_spaces + "Exit!\n") + exit(-1) + + return file_config diff --git a/AFM_thumbs/Initialize.pyc b/AFM_thumbs/Initialize.pyc new file mode 100755 index 0000000000000000000000000000000000000000..fdea305f8d6a3a6c61576d903d3292cc1a0409de GIT binary patch literal 4965 zcmcIoQFGhI5k7zvDMGX;OO`3yX$mEA#iovwrtM6}(`4dtZ6{5vq_8KQ;Y z<%Z}tjJ(2fQ}mlgZm_&6`m086vfL8=mXTLkc0}JXa*O3P(O)yN!*W~n+mP49AK~x~ z5w;nui|_`6jtJKoY*0`ydL0B9{TF|SJqu8id=#gH*Fok#dip#JbYKS7uM9+)>AzX& ze>t8_244o*H705r45czA-HORDO-9ktD2k;&4fNP3Y+kEi#&#-W(}f(N%jZlt)S*(4tj2Yj;xcA9t{+FqWbd)BK(^;ZrcIn|ihK{;{21(LF`24hA^k`ok zMrZ^>Zxu*WGtKAf@mSfYCx8bN8Aic@8u_2k23Tt5t8tLY@Zi@-?!h2R4v=VHQ|?q1 zewx6&Adb%DJ_5amnWD1CFBU{(?ESkKR^*U!tEP41vR2!{a_gtT?jN&|mKZG#(*cM}zY#bpv4TD{Lf&3j>?n zJB{Wt)`Su!V4b- zQKDN=CE!o9bjms`VT5O7VZP97g_??vk|1U$dF+f`P*Y6I)|piPD3h;v;$Sk3BRvZx zD+S3>EO{n13=)4f4b#(vjnt`>Q-Acn8DwEP4wTewENccI`Em{hp(stqZ#jm;FAkq@ zC$dNk#dtUlk_0KE?9Ol=*_Sgvcr7!^4w1o`KMIJCasdg%YMR*O%pc-F53+!GhaH0D zr8v&~3DQHE2MXrKCqx8}GXYHH(4YIfG6!JfI2gbuN+hy1^cPnY7QRs+A997<#nNP& zVqL{vvPStd>3MTcFnl$O3}tGk=nQ2XEI0?Oqoavj&QXxmQk~MMzCV&AYOjza@hVlY zee!mIMp&(H@o_Brw750+n_DJd+61&exQhG*tW11lQ9;qRc%f_Jn7Q`E7TMo;42)|F z5)TD-|8Y|sujV#igD;`q5?$OUx)(wuzbsUoZ&JypSj(qA7vgJMz%=h~3+k~1tqqE< zi!Q#p;fm;@zZ*7kxhcBOJ|TaT(z3cDxO=^r(X50T39pT_SP(J$9hNtQzRA%&v~m|V z*|iRPflg$nBQ6l>mN>p8&MoS=cs}$PE)-IYEzuoX$|#vp6XsMR-9TBWahBhO2ur2 z%^EyA%vii^hD8wbI$Jg>mJPQ2xUgjLvL)6jEt?g~CR>__uqKPvs|$OX!b;B7pYs(= z<|*5xcM~Or_`uw7Jf;TP#{1K7#FwF$W9b6Bbc!8K_r*QFbL=^48$y^$ zd8D+v>+sp<%S{qQv0~o*-HZ8iCdX%|i!cNg_TGTG#}`n#PoAdPNt7HdFLq3bPlH%V zkM1};2|2}+0Px)rdsT?ktUz~3=FVV%noM4_F1;|lSG(IxK&Vj6@mcBBR z(k)xfrZS7ttP;iDYWD{|F}kV@uVWZ1mf-{|~Ic2L`7Ircyu8S{2*S5h_9jK4!90baA&Qwl)pmI>N87J9c zYBy7Z)7OYQh*nJx>I0K27_;;VM3?(iI(o&YwQGE8=WC+8pp>B2fbodgZxP)fC+79@ zP|>^1BaOpJ*P@3m(TsUvGfbl>r;ehF2vbawYC|u(j=Fbmoq6bt90uxG`4kAGp(*cB91A>`z8}-c@w?=}@_JR$W}oTsn@9 za?uany~?}XS3wp916+9U{rrA2Bp2?^?Ld0yT|ifGr+tCb|t$qK@Z&LkACxo z=RWZ~w7a{zoUm&W;HZ7rT}hei$@ii}=^&0du+wphU~oY{%7V$hqlk5$%p<+)@XrE0 zIz3F0hiM|cr;xm7)OX-mQ z><~%Vo6cjaVQ+#Qw(ZT8`=E{#`4OF7^(GqP!?wL)UHQ~n_14c@zyBXv7F3o1 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/Linalg.py b/AFM_thumbs/Linalg.py new file mode 100755 index 0000000..c17b9db --- /dev/null +++ b/AFM_thumbs/Linalg.py @@ -0,0 +1,251 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import scipy +from scipy import linalg +import numpy as np +from AFM_thumbs.Variables import globvar_spaces +from AFM_thumbs.Variables import globvar_LINALG +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_ThumbPara + + +def linalg_plane_fit(size_x, size_y, data): + + size_x_float = float(size_x) + size_y_float = float(size_y) + + if size_x == 512 and size_y == 512: + + M = globvar_LINALG.plane_M512 + x_vec = globvar_LINALG.plane_x_vec512 + y_vec = globvar_LINALG.plane_y_vec512 + + elif size_x == 1024 and size_y == 1024: + + M = globvar_LINALG.plane_M1024 + x_vec = globvar_LINALG.plane_x_vec1024 + y_vec = globvar_LINALG.plane_y_vec1024 + + else: + + x_vec = np.arange(size_x_float) + y_vec = np.arange(size_y_float) + + x = x_vec.sum() * size_x_float + y = y_vec.sum() * size_y_float + xx = (x_vec * x_vec).sum() * size_x_float + yy = (y_vec * y_vec).sum() * size_y_float + xy = (y_vec * (x / size_x_float)).sum() + + M = scipy.mat([[xx,xy,x], + [xy,yy,y], + [x,y,size_x_float*size_y_float]]) + + z = data.sum() + xz = (data * x_vec).sum() + yz = (data * y_vec.reshape(size_y,1)).sum() + B = scipy.mat([[xz], [yz], [z]]) + + c,resid,rank,sigma = linalg.lstsq(M,B) + + array_one = np.array([[1 for i in range(size_x)] for j in range(size_y)]) + + plane_const = array_one * c[2][0] + plane_x = array_one * x_vec * c[0][0] + plane_y = array_one * y_vec.reshape(size_y,1) * c[1][0] + plane = plane_const + plane_x + plane_y + + # The plane substraction + data = data - plane + + # Put zero onto lowest value + # min_value = min(data) + # data = data - float(min_value) + + return data + + +def linalg_line_fit(size_x, size_y, data): + + size_x_float = float(size_x) + size_y_float = float(size_y) + + if size_x == 512 and size_y == 512: + + M = globvar_LINALG.line_M512 + x_vec = globvar_LINALG.line_x_vec512 + + elif size_x == 1024 and size_y == 1024: + + M = globvar_LINALG.line_M1024 + x_vec = globvar_LINALG.line_x_vec1024 + + else: + + x_vec = np.arange(size_x_float) + x = x_vec.sum() + xx = (x_vec * x_vec).sum() + M = scipy.mat([[xx,x], + [x,size_x_float]]) + + plane = [] + for line in data: + + y = sum(line) + xy = sum(line*x_vec) + + B = scipy.mat([[xy],[y]]) + c,resid,rank,sigma = linalg.lstsq(M,B) + + plane.append([i * c[0][0] + c[1][0] for i in range(size_x)]) + + # The plane substraction + data = data - plane + + # Put zero onto lowest value + # min_value = min(data) + # data = data - float(min_value) + + return data + + +def initialize_linalg(): + + # Plane + x_vec = np.arange(512) + y_vec = np.arange(512) + x = x_vec.sum() * 512.0 + y = y_vec.sum() * 512.0 + xx = (x_vec * x_vec).sum() * 512.0 + yy = (y_vec * y_vec).sum() * 512.0 + xy = (y_vec * (x / 512.0)).sum() + + globvar_LINALG.plane_M512 = scipy.mat([[xx,xy,x], + [xy,yy,y], + [x,y,512.0*512.0]]) + globvar_LINALG.plane_x_vec512 = x_vec + globvar_LINALG.plane_y_vec512 = y_vec + + x_vec = np.arange(1024) + y_vec = np.arange(1024) + x = x_vec.sum() * 1024.0 + y = y_vec.sum() * 1024.0 + xx = (x_vec * x_vec).sum() * 1024.0 + yy = (y_vec * y_vec).sum() * 1024.0 + xy = (y_vec * (x / 1024.0)).sum() + + globvar_LINALG.plane_M1024 = scipy.mat([[xx,xy,x], + [xy,yy,y], + [x,y,1024.0*1024.0]]) + globvar_LINALG.plane_x_vec1024 = x_vec + globvar_LINALG.plane_y_vec1024 = y_vec + + # Line + x_vec = np.arange(512) + x = x_vec.sum() + xx = (x_vec * x_vec).sum() + globvar_LINALG.line_M512 = scipy.mat([[xx,x], + [x,512.0]]) + globvar_LINALG.line_x_vec512 = x_vec + + x_vec = np.arange(1024) + x = x_vec.sum() + xx = (x_vec * x_vec).sum() + globvar_LINALG.line_M1024 = scipy.mat([[xx,x], + [x,1024.0]]) + globvar_LINALG.line_x_vec1024 = x_vec + + +def check_image_properties(data, data_file): + + size_x = int(globvar_AFMdata.x_pixel) + size_y = int(globvar_AFMdata.y_pixel) + size = size_x * size_y + + old_y_size = "" + old_y_pixel = "" + + # Part 1 + # ====== + # + # We first put all NaNs onto the mean value! This is important for, e.g., + # Nanonis files. + if np.isnan(data.min()) or np.isnan(data.max()): + + list_nans = np.where(np.isnan(data))[0] + data_clean = np.delete(data, list_nans) + data_mean = np.mean(data_clean) + + for nan in list_nans: + data[nan] = data_mean + + # Part 2 + # ====== + # + # Check now the lenght of the array, and send the true size, if the image + # is not complete (important for Omicron SCALA images that were stored + # before the complete image was finished). + if len(data) != size: + size_diff = len(data) - size + print + print(globvar_spaces + "Attention, error in data file!") + print(globvar_spaces + "Length of data is not equal to size_x * size_y") + print(globvar_spaces + "Size x,y : "+str(size_x) + "x" + \ + str(size_y) + ", " + str(size_x*size_y)) + print(globvar_spaces + "Data : "+str(len(data))) + print(globvar_spaces + "Data-Size : "+str(size_diff)) + print(globvar_spaces + "File : " + data_file) + + # This is for ONE line: + if abs(size_diff) < size_x: + data = data[ : -(size_x + size_diff) ] + size_y -= 1 + print(globvar_spaces + "Error has been fixed by removing one" + + " line from the data.") + # This is for several lines. + elif abs(size_diff) > size_x: + remove_lines = int(size_diff / size_x) + remove_data = size_diff % size_x + size_y -= abs(remove_lines) + if remove_data != 0: + data = data[ : -remove_data ] + print(globvar_spaces + "Error has been fixed by removing " + + str(abs(remove_lines)) + " lines from the data.") + + old_y_size = globvar_AFMdata.y_size + old_y_pixel = globvar_AFMdata.y_pixel + globvar_AFMdata.y_pixel = str(size_y) + globvar_AFMdata.y_size = str(float(globvar_AFMdata.x_size) * \ + (float(size_y)/float(size_x))) + # Two digits after the .dot. . + globvar_AFMdata.y_size = globvar_AFMdata.y_size[: \ + globvar_AFMdata.y_size.find(".")+2] + + return data, old_y_size, old_y_pixel + + + diff --git a/AFM_thumbs/Linalg.pyc b/AFM_thumbs/Linalg.pyc new file mode 100755 index 0000000000000000000000000000000000000000..957e093395c72c47dd702bb34b99e544eb8da71f GIT binary patch literal 5128 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 N`kyO5DBmvc{tu>(z@`8I literal 0 HcmV?d00001 diff --git a/AFM_thumbs/Nanotec_DULCINEA.py b/AFM_thumbs/Nanotec_DULCINEA.py new file mode 100755 index 0000000..765b179 --- /dev/null +++ b/AFM_thumbs/Nanotec_DULCINEA.py @@ -0,0 +1,452 @@ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import os +import numpy as np + +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import Nanotec_DULCINEA_suffix +from AFM_thumbs.Variables import Nanotec_DULCINEA_forward +from AFM_thumbs.Variables import Nanotec_DULCINEA_backward +from AFM_thumbs.Variables import Nanotec_DULCINEA_must_exist +from AFM_thumbs.Linalg import linalg_plane_fit +from AFM_thumbs.Linalg import linalg_line_fit +from AFM_thumbs.Linalg import check_image_properties +from AFM_thumbs.Thumbs import create_thumb_images +from AFM_thumbs.Initialize import initialize_AFM_data + +from AFM_thumbs.Channel import proceed_with +from AFM_thumbs.Channel import line_fit +from AFM_thumbs.Channel import plane_fit +from AFM_thumbs.Channel import rename_channel + +def is_Nanotec_DULCINEA_file(directory, files): + + list_directories_par = [] + + # A directroy is only interesting if there is at least + # one par and tf0 file. + FLAG = False + for filename in files: + file_name = os.path.join(directory, filename) + if FLAG == True: + if os.path.isdir(directory): + list_directories_par.append(directory) + break + if file_name[-6:] == Nanotec_DULCINEA_must_exist: + FLAG = True + + return list_directories_par + + +def prepare_Nanotec_DULCINEA_images(AFMfile): + + file_basis = AFMfile[:-5] + + read_Nanotec_DULCINEA_data(file_basis + Nanotec_DULCINEA_suffix[0]) + + for (image_nr, data_file) in enumerate(globvar_AFMdata.datfile): + + if proceed_with(image_nr,globvar_AFMdata.scandir[image_nr]): + + # Now, we determine only the file name without path. + # The way to do it is a bit complicated but does not depend + # on the system. + + # Cut everything til the first appereabce of "." from the left ... + position = data_file.find(".") + # and note the suffix. + data_file_only_suffix = data_file[position+1:] + # Cat the basis of the file name and the suffix + data_file_name = file_basis + data_file_only_suffix + + # If the file doesn't exist continue. But this would be strange, so + # output an error message. + if not os.path.isfile(data_file): + print(globvar_spaces + "The AFM data file ...\n<" + \ + + ">\n... does not exist (?).\n\n") + print + continue + + # If the thumb image exists continue with next one ... . + # (Don't calculate a second time.) + if globvar_ThumbPara.png: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + data_file_name) + ".png" + else: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + data_file_name) + ".jpeg" + + if os.path.isfile(image_path): + continue + datafile = open(data_file, 'rb') + data = datafile.read() + datafile.close() + + # Read the position of the binary data. + pos = data.find(b"[Header end]") + 12 + # data[pos:pos+12].decode("utf-8") + data = data[pos:-2] + + size_x = int(globvar_AFMdata.x_pixel) + size_y = int(globvar_AFMdata.y_pixel) + + # Reopen the file + datafile = open(data_file, 'rb') + # Move to position in file + datafile.seek(pos,0) + # Straight to numpy data (no buffering) + data = np.fromfile(datafile,dtype = np.int16,count = size_x*size_y) + datafile.close() + + # old_y_size and old_y_pixel are needed to temporarily store + # the original size in y (nm and pixel). This is then used + # at the end to put back the original values for + # globvar_AFMdata.y_size and globvar_AFMdata.y_pixel, for the + # text in the thumbs. + data, old_y_size, old_y_pixel = check_image_properties(data, data_file) + # If there is some corrupt image the y value, which has been + # changed in check_image_properties, needs to be updated. + size_y = int(globvar_AFMdata.y_pixel) + + # First, transform the integers into floats. This is needed for all + # mathematical operations. + data = data.astype(float) + # Average value + average = np.average(data) + # Put the lowest point onto ZERO. + data = data - data.min() + + # Scale the image with the values found in the file. + z_diff_unit = float(globvar_AFMdata.z_amplitude[image_nr]) + z_diff = float(data.max()) - float(data.min()) + factor = z_diff_unit / z_diff + data = data * factor + # Calibrate the average value and write it into the + # globvar_AFMdata structure. + globvar_AFMdata.z_average = average * factor + + # Make now a 2D array. + data.shape = np.array([size_y, size_x]) + + # Mirror the data along x and y + data = np.fliplr(data) + data = np.flipud(data) + + # Line fit + if line_fit(image_nr,globvar_AFMdata.scandir[image_nr]): + data = linalg_line_fit(size_x, size_y, data) + + # Plane fit + if plane_fit(image_nr,globvar_AFMdata.scandir[image_nr]): + data = linalg_plane_fit(size_x, size_y, data) + + create_thumb_images(data,image_nr,data_file_name,data_file_name) + + if old_y_size != "" and old_y_pixel != "": + globvar_AFMdata.y_size = old_y_size + globvar_AFMdata.y_pixel = old_y_pixel + + else: + continue + + return True + + +def read_Nanotec_DULCINEA_data(AFM_file): + + initialize_AFM_data() + + # Go through the directory and find all files of ONE measurement. + AFMfiles = filter(lambda x: x.startswith(AFM_file[:-5]), + os.listdir(globvar_AFMdir.working_directory)) + AFMfiles = sorted(AFMfiles) + + # For all those files, do ... + for AFMfile in AFMfiles: + + AFMfile_split = AFMfile.split(".") + + # Check the AFM file: + if AFMfile_split[-2] == "b" or AFMfile_split[-2] == "f": + # So, there is a ".f." or ".b.". If now the last suffix is NOT + # in the list of known 'channels', continue with the loop. In other + # words an unknown channel has been found, which is not supported. + if AFMfile[-5:] not in Nanotec_DULCINEA_suffix: + continue + # No second suffix ".f." or ".b." could be found. For some channels have + # something like ".b.2nd.Auxfeed". So, check the 3rd suffix: + else: + if AFMfile_split[-3] == "b" or AFMfile_split[-3] == "f": + # Reconstruct all the 3 suffix + AFMfile_2suffix = "." + \ + AFMfile_split[-3] + "." + \ + AFMfile_split[-2] + "." + \ + AFMfile_split[-1] + # As above, an unknown channel has been found, which is not + # supported. + if AFMfile_2suffix not in Nanotec_DULCINEA_suffix: + continue + + # Strange, not found. It seems to be a completely different file! + else: + continue + + # ... open the file and ... + file_path = os.path.join(globvar_AFMdir.working_directory,AFMfile) + file_p = open(file_path, "rb") + + globvar_AFMdata.datfile.append(file_path) + + if Nanotec_DULCINEA_backward in AFMfile: + globvar_AFMdata.scandir.append("backward") + if Nanotec_DULCINEA_forward in AFMfile: + globvar_AFMdata.scandir.append("forward") + + # ... find the data for the lists from above. + for line in file_p: + + line = line.decode("utf-8") + + if "[Head Settings]" in line: + break + + if "Acquisition channel:" in line: + position1 = str.find(line, ":")+2 + rename_channel(line[position1:]) + + if "Acquisition primary channel:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Conversion Factor 00:" in line: + globvar_AFMdata.unit.append(line.rsplit(" ")[-1].rstrip()) + globvar_AFMdata.z_factor.append(line.rsplit(" ")[-2].rstrip()) + + if "Z Calibration:" in line: + list_split = line.split(" ") + globvar_AFMdata.z_calibration.append(list_split[-2]) + + if "Maximum: " in line: + list_split = line.split(" ") + globvar_AFMdata.z_max.append(list_split[-1]) + + if "Minimum: " in line: + list_split = line.split(" ") + globvar_AFMdata.z_min.append(list_split[-1]) + + if "Z Amplitude: " in line: + list_split = line.split(" ") + globvar_AFMdata.z_amplitude.append(list_split[-2]) + + file_p.close() + + file_path = os.path.join(globvar_AFMdir.working_directory,AFM_file) + file_p = open(file_path, "rb") + + for line in file_p: + + line = line.decode("utf-8") + + if "[Head Settings]" in line: + break + + if "Angle: " in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.angle = line[position1:].rstrip() + + if "Set Point: " in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.feedback = line[position1:].rstrip() + + if "Signal Gain:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.gain_signal = line[position1:].rstrip() + + if "Topography Bias:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.voltage = line[position1:].rstrip() + + if "X Amplitude:" in line: + position1 = str.find(line, ":")+2 + position2 = str.find(line, "nm")-1 + globvar_AFMdata.x_size = line[position1:position2] + + if "X Offset:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.x_off = line[position1:].rstrip() + + if "X-Frequency:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.speed = line[position1:].rstrip() + + if "XY Gain:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.gain_xy = line[position1:].rstrip() + + if "Y Amplitude:" in line: + position1 = str.find(line, ":")+2 + position2 = str.find(line, "nm")-1 + globvar_AFMdata.y_size = line[position1:position2] + + if "Y Offset:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.y_off = line[position1:].rstrip() + + if "Z Gain:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.gain_z = line[position1:].rstrip() + + if "Z Offset:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Integral:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.gain_int = line[position1:].rstrip() + + if "Proportional:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.gain_prop = line[position1:].rstrip() + + if "Tilt X:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Tilt Y:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Acquisition time:" in line: + position1 = str.find(line, ":")+2 + position2 = str.rfind(line, ":") + globvar_AFMdata.date = line[position1:position2].rstrip() + + if "Conversion Factor 01:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Conversion Offset 00:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Conversion Offset 01:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Force constant:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Head type:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Image Data Type:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Number of columns:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.x_pixel = line[position1:].rstrip() + + if "Number of rows:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.y_pixel = line[position1:].rstrip() + + if "X scanning direction:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Y scanning direction:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Head Name:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "X Calibration:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Y Calibration:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Acquired with version:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "CH 12:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "CH 13:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "CH 14:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Comments:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "DSP voltage range:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Dulcinea serial number:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Sampling frequency:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Saved with version:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Version:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Z Scale Factor:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + if "Z Scale Offset:" in line: + position1 = str.find(line, ":")+2 + globvar_AFMdata.NONE = None + + # Close the Omicron par file ... + file_p.close() + + return True diff --git a/AFM_thumbs/Nanotec_DULCINEA.pyc b/AFM_thumbs/Nanotec_DULCINEA.pyc new file mode 100755 index 0000000000000000000000000000000000000000..1b55f89c7c9b1884b06afd7680c7eebf4d083c0a GIT binary patch literal 8901 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 VV8JMuLwK^?>cTi{sWPA9sK|R literal 0 HcmV?d00001 diff --git a/AFM_thumbs/Omicron_SCALA.py b/AFM_thumbs/Omicron_SCALA.py new file mode 100755 index 0000000..650b7d6 --- /dev/null +++ b/AFM_thumbs/Omicron_SCALA.py @@ -0,0 +1,417 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import sys +import os +import numpy as np + +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_thumb_size_x +from AFM_thumbs.Variables import globvar_thumb_size_y +from AFM_thumbs.Variables import Omicron_SCALA_forward +from AFM_thumbs.Variables import Omicron_SCALA_backward +from AFM_thumbs.Linalg import linalg_plane_fit +from AFM_thumbs.Linalg import linalg_line_fit +from AFM_thumbs.Linalg import check_image_properties +from AFM_thumbs.Thumbs import create_thumb_images +from AFM_thumbs.Thumbs import create_thumb_spectra +from AFM_thumbs.Initialize import initialize_AFM_data + +from AFM_thumbs.Channel import proceed_with +from AFM_thumbs.Channel import line_fit +from AFM_thumbs.Channel import plane_fit +from AFM_thumbs.Channel import rename_channel + +def is_omicron_SCALA_file(directory, files): + + list_directories_par = [] + + # A directroy is only interesting if there is at least + # one par and tf0 file. + FLAG_par = False + FLAG_tf0 = False + for filename in files: + file_name = os.path.join(directory, filename) + if FLAG_par == True and FLAG_tf0 == True: + if os.path.isdir(directory): + list_directories_par.append(directory) + break + if file_name[-4:] == ".par": + FLAG_par = True + if file_name[-4:] == ".tf0": + FLAG_tf0 = True + + return list_directories_par + + +def read_Omicron_SCALA_data(par_file): + + initialize_AFM_data() + + par_file_path = os.path.join(globvar_AFMdir.working_directory,par_file) + par_file_p = open(par_file_path, "r") + + # The spectroscopy parameters are read ................................. . + for line in par_file_p: + if "; Spectroscopic Channels." in line: + break + + for line in par_file_p: + + if ";Parameter" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_x_label.append(split_list[0]) + if split_list[0] == "Z": + globvar_AFMdata.spec_x_unit.append("nm") + elif split_list[0] == "V": + globvar_AFMdata.spec_x_unit.append("V") + elif split_list[0] == "U": + globvar_AFMdata.spec_x_unit.append("V") + elif split_list[0] == "Macro": + globvar_AFMdata.spec_x_unit.append("a.u.") + else: + globvar_AFMdata.spec_x_unit.append("a.u.") + if ";Display name" in line: + pos = line.find(";") + line = line[34:pos] + line = line.replace(" ", "") + globvar_AFMdata.spec_y_label.append(line) + if ";Physical unit" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_y_unit.append(split_list[0]) + if ";Maximum value in physical unit" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_y_factor.append(float(split_list[0])) + if ";Number of spectroscopy points" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_points.append(split_list[0]) + if ";Feedback On/Off" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_feedback.append(split_list[0]) + if ";Acquisition time per spectroscopy point" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_acquisition.append(split_list[0]) + if ";Delay time per spectroscopy point" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_delay.append(split_list[0]) + # Added on 2017-07-28 + if ";Filename" in line: + split_list = line.rsplit() + globvar_AFMdata.spec_files.append(split_list[0]) + + # Go to the beginning of the file. + par_file_p.seek(0, 0) + + # The image parameters are read ................................. . + for line in par_file_p: + + # Jump over the spectroscopy part + if "; Spectroscopic Channels." in line: + for line in par_file_p: + if "; Measurement parameters." in line: + break + + if "Date" in line: + position1 = str.find(line, ":") + globvar_AFMdata.date = line[position1+2:-7]+", "+line[-7:-1] + if "Field X Size" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.x_size = line[position1:position2] + if "Field Y Size" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.y_size = line[position1:position2] + if "Image Size in X" in line: + position1 = str.find(line, ":") + globvar_AFMdata.x_pixel = line[position1+2:-1] + if "Image Size in Y" in line: + position1 = str.find(line, ":") + globvar_AFMdata.y_pixel = line[position1+2:-1] + if "X Offset" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.x_off = line[position1:position2] + if "Y Offset" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.y_off = line[position1:position2] + if "Measured Gap Voltage" not in line: + if "Gap Voltage" in line: + position1 = str.find(line, ":")+2 + # Change 2017-06-25 + # From '+2' to + '4' => two digits more for Ugap + position2 = -(len(line)-str.rfind(line, "."))+4 + globvar_AFMdata.voltage = line[position1:position2] + if "Feedback Set" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+4 + globvar_AFMdata.feedback = line[position1:position2] + if "Loop Gain" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.gain = line[position1:position2] + if "Scan Speed" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.speed = line[position1:position2] + if "Amplitude" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.amplitude = line[position1:position2] + if "Scan Angle" in line: + position1 = str.find(line, ":")+2 + position2 = -(len(line)-str.rfind(line, "."))+2 + globvar_AFMdata.angle = line[position1:position2] + if "Topographic Channel :" in line: + position1 = str.find(line[34:], " ") + 34 + if line[position1+1] is not " ": + position1 = position1 + 2 + # 'rename_channel': see in Channel.py + rename_channel(line[34:position1]) + if ";Physical unit" in line: + split_list = line.rsplit() + globvar_AFMdata.unit.append(split_list[0]) + if ";Filename" in line: + split_list = line.rsplit() + globvar_AFMdata.datfile.append(split_list[0]) + if Omicron_SCALA_backward in split_list[0]: + globvar_AFMdata.scandir.append("backward") + if Omicron_SCALA_forward in split_list[0]: + globvar_AFMdata.scandir.append("forward") + if "Maximum value in physical unit" in line: + split_list = line.rsplit() + globvar_AFMdata.z_factor.append(float(split_list[0])) + + # We calculate now the total time of the spectroscopy in ms. + for tau, delay, points in zip(globvar_AFMdata.spec_acquisition, + globvar_AFMdata.spec_delay, + globvar_AFMdata.spec_points): + time = float(points) * ( float(tau) + float(delay) ) * 1000.0 + globvar_AFMdata.spec_time.append("%.1f" % time) + + # Close the Omicron par file ... + par_file_p.close() + + return True + + +def prepare_Omicron_SCALA_images(par_file): + + # Loop over all channels. The channels are stored in the list + # 'globvar_AFMdata.datfile', which contains the file names (without path) + # as values. + for (image_nr, data_file) in enumerate(globvar_AFMdata.datfile): + + # The definition 'proceed_with' is very important! It is 'connected' + # with the GUI of AFM_thumbs where one can choose if a channel in a + # specific scanning direction shall be represented in a pdf file or not. + if proceed_with(image_nr,globvar_AFMdata.scandir[image_nr]): + + # Path to the image + data_file_name = data_file + data_file = os.path.join(globvar_AFMdir.working_directory, + data_file) + + # Very strange 'if' but anyway ... if yes then simply continue. + if not os.path.isfile(data_file): + continue + + # Image file name + image_name = data_file_name[:-4] + if image_name[2] == "_": + image_name = image_name[0:1]+"00"+image_name[1:] + if image_name[3] == "_": + image_name = image_name[0:1]+"0"+image_name[1:] + image_name = image_name + "_" + str(image_nr) + + if globvar_ThumbPara.png: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".png" + else: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".jpeg" + + # If the thumb image exists continue with next one ... . + # (Don't calculate a second time.) + if os.path.isfile(image_path): + continue + + data = np.fromfile(file=data_file,dtype=np.int16) + + size_x = int(globvar_AFMdata.x_pixel) + size_y = int(globvar_AFMdata.y_pixel) + + # Data is cut by the definition check_image_properties. + # + # Note + # ==== + # old_y_size and old_y_pixel are needed to temporarily store + # the original size in y (nm and pixel). This is then used + # at the end to put back the original values for + # globvar_AFMdata.y_size and globvar_AFMdata.y_pixel, for the + # text in the thumbs. + data, old_y_size, old_y_pixel = check_image_properties(data, data_file) + # If there is some corrupt image the y value, which has been + # changed in 'check_image_properties', needs to be updated. + size_y = int(globvar_AFMdata.y_pixel) + + data = data.byteswap() + data = (globvar_AFMdata.z_factor[image_nr] * data) / 32767.0 + globvar_AFMdata.z_average = np.average(data) + + if globvar_ThumbPara.minimum_on_zero: + data = data - float(min(data)) + data.shape = np.array([size_y, size_x]) + + # Mirror the data along y + data = np.flipud(data) + + # Line fit + if line_fit(image_nr,globvar_AFMdata.scandir[image_nr]): + data = linalg_line_fit(size_x, size_y, data) + + # Plane fit + if plane_fit(image_nr,globvar_AFMdata.scandir[image_nr]): + data = linalg_plane_fit(size_x, size_y, data) + + create_thumb_images(data, image_nr, image_name, data_file_name) + + if old_y_size != "" and old_y_pixel != "": + globvar_AFMdata.y_size = old_y_size + globvar_AFMdata.y_pixel = old_y_pixel + + else: + continue + + return True + + +def prepare_Omicron_SCALA_spectra_curves(par_file): + + """ + print(par_file) + print(globvar_AFMdata.spec_files, + globvar_AFMdata.spec_x_unit, + globvar_AFMdata.spec_x_label, + globvar_AFMdata.spec_y_unit, + globvar_AFMdata.spec_y_label, + globvar_AFMdata.spec_y_factor, + globvar_AFMdata.spec_points, + globvar_AFMdata.spec_feedback, + globvar_AFMdata.spec_acquisition, + globvar_AFMdata.spec_delay) + """ + + i = 0 + + for data_file in globvar_AFMdata.spec_files: + + data_file_name = data_file + data_file = os.path.join(globvar_AFMdir.working_directory,data_file) + + # If the file does not exist continue loop + if not os.path.isfile(data_file): + continue + + # If the file is 0Byte large (empty) continue loop (Do not consider + # the file) + if os.stat(data_file)[6] == 0: + continue + + Channel = int(data_file[-1:]) + + # Image name - Cut the suffix. + image_name = data_file_name[:-4] + + # Put in some zeros after the 'm'. + if image_name[2] == "_": + image_name = image_name[0:1]+"00"+image_name[1:] + if image_name[3] == "_": + image_name = image_name[0:1]+"0"+image_name[1:] + # Suffix. New since 2017-07-28. + image_name = image_name + "_s0" + str(Channel) + + if globvar_ThumbPara.png: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".png" + else: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".jpeg" + + if os.path.isfile(image_path): + continue + + data_file_p = open(data_file, "r") + + for line in data_file_p: + if "END COORD" in line: + break + + for line in data_file_p: + if "BEGIN" in line: + break + + x_data_list = [] + y_data_list = [] + + for line in data_file_p: + + if "BEGIN" in line: + continue + + x_data = [] + y_data = [] + for line in data_file_p: + + if "END" in line: + break + + split_list = line.rsplit() + + x_data.append(split_list[0]) + y_data.append(globvar_AFMdata.spec_y_factor[i] + * (float(split_list[1])/32767.0 )) + + if x_data != [] and y_data != []: + x_data_list.append(x_data) + y_data_list.append(y_data) + + + # Close the Omicron file + data_file_p.close() + + create_thumb_spectra(x_data_list, + y_data_list, + i, + image_name, + image_path, + globvar_AFMdata.spec_y_label[i]) + i += 1 + + return True diff --git a/AFM_thumbs/Omicron_SCALA.pyc b/AFM_thumbs/Omicron_SCALA.pyc new file mode 100755 index 0000000000000000000000000000000000000000..22b452dc96f48d33860a96515668bc95e6102dab GIT binary patch literal 9209 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 C$Zr<_ literal 0 HcmV?d00001 diff --git a/AFM_thumbs/PDF.py b/AFM_thumbs/PDF.py new file mode 100755 index 0000000..b6a23b6 --- /dev/null +++ b/AFM_thumbs/PDF.py @@ -0,0 +1,267 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import os +import shutil +import re + +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_spaces + + +# This is the definiton which produces the pdf. We will make use of +# graphicsmagic's 'gm montage' to realize the montage of thumbnail images in a +# x/y pattern into png/jpeg sheets. After, imagemagick's 'convert' will be used +# to create pdfs from the pngs/jpegs. Last, it is pdftk that puts together all +# pdfs. +# +# May be, all this can be changed such that we either have only graphicsmagic +# or imagemagick. Can we avoid also pdftk? Let's see in future. +def prepare_PDFs(): + + # Decide over the image ending + if globvar_ThumbPara.png: + end = '.png' + else: + end = '.jpeg' + + # Get the list of images in the thumbnail directory. + image_file_list = filter(lambda x: x.endswith(end), + os.listdir(globvar_AFMdir.thumbnail_directory)) + image_file_list = list(image_file_list) + + if image_file_list == []: + print(globvar_spaces + "There are no images in the directory\n" + + globvar_spaces + globvar_AFMdir.thumbnail_directory + " !\n" + + globvar_spaces + "We leave this out ... .\n") + return False + + # The list is well ordered thanks to the 001, 002, etc. order (see + # definitions in Omicron_SCALA.py, Nanotec_DULCINEA.py and RHK.py) + image_file_list.sort() + + # Initialize the string for gm montage + # p: font size of the title, scale with number of images in one row + para_mon_p = globvar_ThumbPara.col * 8 + str_tile = str(globvar_ThumbPara.col) + "x" + str(globvar_ThumbPara.row) + + geo_x = max(globvar_ThumbPara.geometry_x) + geo_y = max(globvar_ThumbPara.geometry_y) + + # First part of the string for graphicsmagick with standard parameters for + # all pdfs. + para_gm_mon_1 = ("gm montage -geometry " + str(geo_x) + "x" + str(geo_y) + + " -pointsize " + str(para_mon_p) + + " -title \"" + globvar_AFMdir.working_directory + "\"" + + " -tile " + str_tile + " " ) + + # Initialization of the string for gm and convert + m_str = "" + r = 0 # counter - total number of images on one page + q = 0 # counter - number of pages + FLAG_first_spec_image = False + + # This "for loop" takes up to 'globvar_ThumbPara.col*globvar_ThumbPara.row' + # images for one page. The code is done such that first single pdf pages + # are created in the thumbnail directory. The reason is that graphicsmagic + # is asking for too much RAM otherwise. After all, pdftk puts together + # all pdf pages (see below). + # + # This was strongly improved on 2017-07-28. + for image_file in image_file_list: + + if r < globvar_ThumbPara.col*globvar_ThumbPara.row: + + # If a spectroscopy image appears then ... + if "_s" in image_file: + #if image_file[9:10] == "s": + + # For the first spectroscopy image: + if "_s00" in image_file: + #if image_file[9:11] == "s0": + + # Note that there is some spectroscopy data. + FLAG_first_spec_image = True + + # Number of free slots in a row. + if r % globvar_ThumbPara.col == 0: + free_slots_in_row = 0 + else: + free_slots_in_row = globvar_ThumbPara.col - (r % globvar_ThumbPara.col) + + # If there is still some place in the row, fill it + # with dummies. + if free_slots_in_row != 0: + for i in range (free_slots_in_row): + m_str = m_str + " \"" + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + "dummy_image.png\"") + r += 1 + # ... if it is an image then ... + else: + # Uuups, the last image was obviously a spectroscopy image, now + # it is an SPM image. If so, new row: + if FLAG_first_spec_image == True: + + # Number of free slots in a row. + if r % globvar_ThumbPara.col == 0: + free_slots_in_row = 0 + else: + free_slots_in_row = globvar_ThumbPara.col - (r % globvar_ThumbPara.col) + + # If there is still some place in the row, fill it + # with dummies. + if free_slots_in_row != 0: + for i in range (free_slots_in_row): + m_str = m_str + " \"" + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + "dummy_image.png\"") + r += 1 + + FLAG_first_spec_image = False + + # Put image and ... + m_str = m_str + " \"" + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + image_file) + "\"" + # ... image counter one up + r += 1 + + # globvar_ThumbPara.col*globvar_ThumbPara.row images are + # collected, or, end of image_file_list. So then do: + else: + # Create only one page first! + # Reason for this: If about 20 pages shall be created the pages + # cannot be stored within one pdf because Graphicsmagick is + # asking for too much RAM!!! So, page after page ... + + # Number of pages + q += 1 + + # Graphicsmagic - montage + last_part = "_%.02d" + end + "\"" + image_string = (para_gm_mon_1 + m_str + " \"" + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + globvar_AFMdir.data_directory_name) + \ + last_part % q) + + os.system(image_string) + + # Imagemagic - pdf + middle_part = "_%.02d" + end + "\" \"" + pdf_string = ("convert -density 300 -compress JPEG -quality " + \ + str(globvar_ThumbPara.jpeg) + " \"" + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + globvar_AFMdir.data_directory_name) + \ + middle_part%q + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + globvar_AFMdir.data_directory_name) + \ + "_%.03d.pdf\" "%q ) + + os.system(pdf_string) + + # Initialize and put in the first image + r = 1 + m_str = "\""+os.path.join(globvar_AFMdir.thumbnail_directory, + image_file) + "\"" + + # If the image is a 'first' spectroscopy image then ... + if "_s00" in image_file: + # if image_file[9:11] == "s00": + # Note that there is some spectroscopy data. + FLAG_first_spec_image = True + + + # if there are remaining pages (r > 1) put them on one page + if r > 1: + + q += 1 + + last_part = "_%.02d" + end + "\"" + image_string = (para_gm_mon_1+m_str + " \"" + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + globvar_AFMdir.data_directory_name) + \ + last_part % q ) + os.system(image_string) + + middle_part = "_%.02d" + end + "\" \"" + pdf_string = ("convert -density 300 -compress JPEG -quality " + \ + str(globvar_ThumbPara.jpeg) + " \"" + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + globvar_AFMdir.data_directory_name) + \ + middle_part%q + \ + os.path.join(globvar_AFMdir.thumbnail_directory, + globvar_AFMdir.data_directory_name) + \ + "_%.03d.pdf\" "%q ) + os.system(pdf_string) + + + + # + # + # Prepare the command string for pdftk for connecting all pdf pages. + # + # + + # This following 'directory thing' was done for pdftk under Windows XP. + # First, we save the directory of AFM_thumbs and ... + AFM_thumbs_directory = os.getcwd() + # ... then, we go inside the thumbnail directory, and later we put the + # system path back onto 'AFM_thumbs_directory' (see below). + os.chdir(globvar_AFMdir.thumbnail_directory) + + # Apply pdftk for putting together the pdfs. + if globvar_AFMdir.pdf_path == "": + pdf_string = ("pdftk *.pdf cat output \"" + \ + globvar_AFMdir.working_directory + \ + globvar_ThumbPara.extension + ".pdf\"" ) + else: + pdf_string = ("pdftk *.pdf cat output \"" + \ + os.path.join(globvar_AFMdir.pdf_path, + globvar_AFMdir.data_directory_name) + \ + globvar_ThumbPara.extension+".pdf\"" ) + # Execute pdftk + os.system(pdf_string) + + # Now, we go back into the directory of AFM_thumbs + os.chdir(AFM_thumbs_directory) + + # If true, delete all thumbnails and pdfs and finally the thumbnail + # directory + if globvar_ThumbPara.thumbs_after: + delete_string = globvar_AFMdir.thumbnail_directory + shutil.rmtree(delete_string) + else: + file_list = os.listdir(globvar_AFMdir.thumbnail_directory) + for f in file_list: + if f.endswith(".pdf"): + os.remove(os.path.join(globvar_AFMdir.thumbnail_directory,f)) + elif f.endswith(end): + if re.search(globvar_AFMdir.data_directory_name,f): + os.remove(os.path.join(globvar_AFMdir.thumbnail_directory,f)) + diff --git a/AFM_thumbs/PDF.pyc b/AFM_thumbs/PDF.pyc new file mode 100755 index 0000000000000000000000000000000000000000..013423fb9dd4d8d6bdbfca83c5dd240c9fc85764 GIT binary patch literal 3497 zcmds4-EJGl6+W}OBqfRzsb4yA(r(nGRt<)C0!A^M#nYKRr(_oEU~61yESNy|AW8By9!g=LN`dpC(pt>xc~4sQE0<*WA(L- zI4{@NuB|^EPScaaFn_}lGYR|Jh}T;=Hcz|7e+B z5GmGLr>I7oGeveqtf;f#XbFc(y1{g3=8$d5{wmWm_lj%@=~1-I0t#2S=f?}Lr0OE9 zfW43ut(2yRnVsZ%%@SD~arQHy5qy-hPXf_{l$@obqc{^G#w2cLcE%<5Fs=9aSk z4ca^-%Kz>}YgE+ftV;R6RJ49IFC4qZ0$!cjhFHdGrda+8Wt($h3yxb@E>>9onM?Ug zb#b381g^0C4?a7fS%V4~xdBHIj}00@goGs8(YU!!~_EbEYO0 z6_(X`127EFmdGo>wnW>V*{US-HWiXk>Pk`v>RJ@tx=P1RnKa+T`kKgADe|>oEEuA< z<~rL~I@>H&!3j>YhOAx-<4xBWxpYUBxpaO<;d@lZ_{^jH&))Y163z?c^ew&~W@|Ek zYjNKw#`JA2Qm&wXc+uOkhf?NByp7PK&DxaRCEmJT93^L&12>tO4QWt@gb74zP2$6R z?@<0xh1FJRwodk48vTHZb=l7TCMvGohqDd3_=1WJROugRwn@b%jebbcJItPcUSZ+> zO|wv`QnQ>6=ZBT@08*L{99HamG};jtx8{8L*Z)(>*A)oD_Xw}jlihc5!#_42`tBqf z7+m$#9ZmG0&rc0Ee*8AjOcNbn&BP@I{ZHg^nZHR(*wk5Mp2v1rK018%qMY(8g3VnF zWbUEcPjwWB`{p$Gbb2z)>@+aLFxS!k1H5JXCvmoqcP+5|RGI73!v_z$lS^C-L?0(% zdJ={AevUcf0Kp%idpgv)_94p8#(tcJ18w{`^X*XkQJm|(9p{&I!}j>^)y*x8N7_$x z_)LQ*HvV{O{cgAGck3}L=`kFJAHzZFr{l~*puacJ<5b)H(l-t4_YIdiD0?FgB^$~=sut&hEJVcF zM{{YcPD@@?iL60L|9K=L`$PC8`3b-R5z8r|FD%Ce3B(yw=5-LBGFl>ZI7NEMG*4}= zb&nIGq;)!erUlb{Zh;Q-{&1I*Qho_ah6KP~2Mo8sGQsb=0QnkB#1^0zaQ=yjfDC9c z-aNa+uO>v0`3I>S`Kj!s$jV&Owd~I=D}4Cr{YOxh8ylF3?w8pq8W&aw@~3bjFv-}O zAkG4g8mB;P8H^;vacHyxMtKm*5GedWBTC~af-l0rA!Z=w+nXR47sDbv;zOk2Ae5Gp zSkVF#R(>kik6cJS0sT9;h&Y<4FxaXC+)Yx7<|{0cyR4R-s@qaqPQ&$;=heNY@|~7y z)gHN3C7`ryr{idv=zF&z*szTag^$x#@>%&W D$Hv7u literal 0 HcmV?d00001 diff --git a/AFM_thumbs/RHK.py b/AFM_thumbs/RHK.py new file mode 100755 index 0000000..9a11ced --- /dev/null +++ b/AFM_thumbs/RHK.py @@ -0,0 +1,674 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import sys +import os +import struct +import numpy +import math +import re + +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_spaces +from AFM_thumbs.Variables import RHK_must_exist +from AFM_thumbs.Variables import RHK_PositionCounter +from AFM_thumbs.Variables import globvar_thumb_size_x +from AFM_thumbs.Variables import globvar_thumb_size_y +from AFM_thumbs.Linalg import check_image_properties +from AFM_thumbs.Thumbs import create_thumb_images +from AFM_thumbs.Thumbs import create_thumb_spectra +from AFM_thumbs.Thumbs import spectra_text +from AFM_thumbs.Linalg import linalg_plane_fit +from AFM_thumbs.Linalg import linalg_line_fit +from AFM_thumbs.Initialize import initialize_AFM_data + +from AFM_thumbs.Channel import proceed_with +from AFM_thumbs.Channel import line_fit +from AFM_thumbs.Channel import plane_fit +from AFM_thumbs.Channel import rename_channel + +# Method to determine whether there are RHK files. +def is_RHK_file(directory, files): + + list_directories_sm4 = [] + + # A directroy is only interesting if there is at least + # one SM4 file. + FLAG = False + for filename in files: + file_name = os.path.join(directory, filename) + if file_name[-4:] in RHK_must_exist: + FLAG = True + if FLAG == True: + if os.path.isdir(directory): + list_directories_sm4.append(directory) + break + + return list_directories_sm4 + +# This method reads out the scan information. +# RHK technology stores all measurement data in one file with no order! +# Because of this the plane- and linefitting settings doesn't matter in the +# current version of this method +def read_RHK_data(SM4_file): + + # _______________________________________________________ Direction check + + initialize_AFM_data() + + sm4_file_path = os.path.join(globvar_AFMdir.working_directory,SM4_file) + + with open(sm4_file_path, "rb") as sm4_datafile: # open file + + sm4_file = sm4_datafile.read() + + globvar_AFMdata.datfile.append(sm4_file_path) + + # ___________________________________________ Reading of the File Header + + # Version Check + current_position = 38 + version = sm4_file[0:current_position] + if not version[2:-2:2] == "STiMage 005.004 1": + version_error = "This method was written on base of SM4 Version " \ + "\'STiMage 005.004 1\'. The results of any other " \ + "version can differ from the expected one. The current " \ + "file version: " + print(globvar_spaces + version_error + version.decode("utf-8")) + print + + # File Header information + total_page_count = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] + current_position += 4 + object_list_count = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] + current_position += 4 + + # Check the Ocject Field size + if not struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] == 12: + obJect_field_error = "Wrong size of object field. " \ + "This may cause a problem." + print(globvar_spaces + obJect_field_error) + print + + current_position += 12 + + # Create Array for the Object List Items + objects = numpy.zeros((object_list_count, 3)) + + for i in range(object_list_count): + objects[i,0] = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] # tape + current_position += 4 + objects[i,1] = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] # offset + current_position += 4 + objects[i,2] = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] # size + current_position += 4 + + # _________________________________________ Content of PAGE INDEX HEADER + + # Page Count Check + page_count = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] + + current_position += 4 + if not page_count == total_page_count: + page_count_error = "The total number of pages is not the same as " \ + "the number of pages. Some data may be left out or doubled." + print(globvar_spaces + page_count_error) + print + + page_object_list_count = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] + current_position += 4 + + current_position += 8 + + # Page Index Object + index_array = numpy.zeros((page_object_list_count, 3)) + + for i in range(page_object_list_count): + index_array[i,0] = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0]; + current_position += 4 + # beginning of the Page index Array + index_array[i,1] = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0]; + current_position += 4 + index_array[i,2] = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0]; + current_position += 4 + + # Page ID Offset + pageindex_page_id_offset = 16 # Page ID hat Laenge 16 + + # for-loop over all channels + for channel in range(page_count): + + # Determining the startpoint + if channel is 0: + next_page_index_array_offset = 0 + current_position = int(index_array[0,1]) + pageindex_page_id_offset + else: + current_position = int(next_page_index_array_offset) \ + + pageindex_page_id_offset + + # Page Index Array + current_position += 4 + + # Page Type + page_data_type = struct.unpack('i', sm4_file \ + [current_position:current_position+4])[0] + current_position += 4 + + pageindex_object_list_count = struct.unpack('i', sm4_file \ + [current_position:current_position+4])[0] + current_position += 4 + current_position += 4 + + # Create an array for the Object List Items + array_objects = numpy.zeros((pageindex_object_list_count, 3)) + + for i in range(pageindex_object_list_count): + array_objects[i,0] = struct.unpack('i', sm4_file[current_position \ + :current_position+4])[0] # tape + current_position += 4 + array_objects[i,1] = struct.unpack('i', sm4_file[current_position \ + :current_position+4])[0] # offset + current_position += 4 + array_objects[i,2] = struct.unpack('i', sm4_file[current_position \ + :current_position+4])[0] # size + current_position += 4 + + # Request of the current position for the start of the next loop + next_page_index_array_offset = current_position + + # Page header + current_position = int(array_objects[0,1])+4 + page_type = str(struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0]) + + # Pixel + current_position = int(array_objects[0,1])+24 + globvar_AFMdata.x_pixel = str(struct.unpack('i', + sm4_file[current_position:current_position+4])[0]) + current_position += 4 + globvar_AFMdata.y_pixel = str(struct.unpack('i', + sm4_file[current_position:current_position+4])[0]) + current_position += 4 + + # Scan direction + current_position = int(array_objects[0,1])+36 + scan_direction = struct.unpack('i', + sm4_file[current_position:current_position+4])[0]; + current_position += 4 + + if scan_direction == 0: + globvar_AFMdata.scandir.append("right") + elif scan_direction == 1: + globvar_AFMdata.scandir.append("left") + elif scan_direction == 2: + globvar_AFMdata.scandir.append("up") + elif scan_direction == 3: + globvar_AFMdata.scandir.append("down") + + current_position += 4 + data_size = struct.unpack('i', sm4_file[current_position: \ + current_position+4])[0] + current_position += 4 + + # Maximum z-Values + globvar_AFMdata.z_min.append(struct.unpack('=l', + sm4_file[current_position:current_position+4])[0]) + current_position += 4 + globvar_AFMdata.z_max.append(struct.unpack('=l', + sm4_file[current_position:current_position+4])[0]) + current_position += 4 + + # Sizes + globvar_AFMdata.x_size = struct.unpack('f', sm4_file[current_position:\ + current_position+4])[0] + current_position += 4 + + globvar_AFMdata.y_size = struct.unpack('f', sm4_file[current_position:\ + current_position+4])[0] + current_position += 4 + + globvar_AFMdata.z_factor.append(struct.unpack('f', + sm4_file[current_position:current_position+4])[0]) + current_position += 4 + + # Offsets + current_position += 4 + globvar_AFMdata.x_off = struct.unpack('f', sm4_file[current_position: \ + current_position+4])[0] + current_position += 4 + globvar_AFMdata.y_off = struct.unpack('f', sm4_file[current_position: \ + current_position+4])[0] + current_position += 4 + + # Speed + current_position += 4 + + globvar_AFMdata.speed = struct.unpack('f', sm4_file[current_position: \ + current_position+4])[0] * \ + int(globvar_AFMdata.x_pixel) * 1000 + current_position += 4 + + # Voltage + globvar_AFMdata.voltage = "{0:.1f}".format(struct.unpack('f', + sm4_file[current_position: \ + current_position+4])[0]) + current_position += 4 + + # Angle + + current_position += 4 + globvar_AFMdata.angle = "{0:.1f}".format(struct.unpack('f', sm4_file[ \ + current_position:current_position+4])[0]) + current_position += 4 + + # Page Header Object List + current_position += 12 + page_header_object_list_count = struct.unpack('i', sm4_file \ + [current_position:current_position+4])[0] + current_position += 4 + + # Go to the page header object list. + current_position = int(array_objects[0,1]) + int(array_objects[0,2]) + + array_header_objects = numpy.zeros((page_header_object_list_count, 3)) + + for i in range(page_header_object_list_count): + array_header_objects[i,0] = struct.unpack('i', \ + sm4_file[current_position:current_position+4])[0] + current_position += 4 + array_header_objects[i,1] = struct.unpack('i', \ + sm4_file[current_position:current_position+4])[0] + current_position += 4 + array_header_objects[i,2] = struct.unpack('i', \ + sm4_file[current_position:current_position+4])[0] + current_position += 4 + + # Go to the text string to get the title. + current_position = int(array_header_objects[0,1]) + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + channel_name = sm4_file[current_position:current_position+str_length:2] + current_position += str_length + + # __________________________________________________ Check the title + + # Substitut all whitespaces with underscore. + channel_name = str(re.sub('\s', '_', channel_name.decode("utf-8"))) + + # Search all special characters and change the title. + if re.search('\W', channel_name): + channel_name_index = re.search('\W', channel_name).start() + channel_name = channel_name[:channel_name_index] + + # If there are underscores at the end of the title, eliminate them. + Space = True + while Space: + if channel_name[-1] == "_": + channel_name = channel_name[:-1] + else: + Space = False + + # Replace all underscores with a simple whitespace + channel_name = re.sub('_', ' ', channel_name) + + # Add the channel name. + rename_channel(channel_name) + + # Skip next 4 strings. + for i in range(4): + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + current_position += str_length + + # date + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + globvar_AFMdata.date = sm4_file[current_position: \ + current_position+str_length:2].decode("utf-8") + current_position += str_length + + # time + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + + globvar_AFMdata.date += ", " + sm4_file[current_position: \ + current_position+str_length:2].decode("utf-8") + current_position += str_length + + # Units + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + globvar_AFMdata.spec_x_unit.append(sm4_file[current_position: \ + current_position+str_length:2].decode("utf-8")) + + # Clemens Barth, 2016-01-15 ........................ + # + # There is a problem with the unit for y! The following code + # needs to be revized. + + current_position += str_length + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + globvar_AFMdata.spec_y_unit.append(sm4_file[current_position: \ + current_position+str_length:2].decode("utf-8")) + + #print(globvar_AFMdata.spec_x_unit, globvar_AFMdata.spec_y_unit) + + # ...................... until here + + current_position += str_length + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + globvar_AFMdata.unit.append(sm4_file[current_position: \ + current_position+str_length:2].decode("utf-8")) + current_position += str_length + + # Topography scale is in nm. + if globvar_AFMdata.channel[-1].find("Topography") != -1 and \ + globvar_AFMdata.unit[-1].find("m") != -1: + globvar_AFMdata.z_factor[-1] = float(globvar_AFMdata.z_factor[-1] \ + *math.pow(10,9)) + globvar_AFMdata.unit[-1] = "nm" + + # Labels + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + globvar_AFMdata.spec_x_label.append(sm4_file[current_position: \ + current_position+str_length:2].decode("utf-8")) + current_position += str_length + str_length = 2*struct.unpack('h', sm4_file[current_position: \ + current_position+2])[0] + current_position += 2 + globvar_AFMdata.spec_y_label.append(sm4_file[current_position: \ + current_position+str_length:2].decode("utf-8")) + current_position += str_length + + # _____________________________________________________ Prepare image + + if channel%2 == 0: + direction = "forward" + elif channel%2 != 0: + direction = "backward" + + if int(page_data_type) != 0: + prepare_RHK_spektra(sm4_file_path, SM4_file, + channel, + int(array_objects[1,1])) + + elif int(page_type) in [16,38,39]: + if globvar_ThumbPara.spektra == 1: + prepare_RHK_spektra(sm4_file_path, + SM4_file, channel, + int(array_objects[1,1])) + + else: + if proceed_with(channel,direction): + prepare_RHK_images(sm4_file_path, SM4_file, + channel, + int(array_objects[1,1])) + + else: + continue + + return True + + +# This methods reads out the measurement data and prepares it for the image. +def prepare_RHK_images(file_path, file_name, image_nr, data_off): + + # If the thumb image exists continue with the next one ... . + # (Don't calculate a second time.) + if image_nr%2 == 0: + direction = "forward" + elif image_nr%2 != 0: + direction = "backward" + + picture_file_name = globvar_AFMdata.channel[-1].replace(" ","_") + "_" + \ + direction + "_" + file_name + + # Add the specific number of the channel. + # Fill empty space with zeros. + if int(RHK_PositionCounter.position / 10) == 0: + picture_file_name = "000" + str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + elif int(RHK_PositionCounter.position / 10) < 10: + picture_file_name = "00" + str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + elif int(RHK_PositionCounter.position / 10) < 100: + picture_file_name = "0" + str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + else: + picture_file_name = str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + if globvar_ThumbPara.png: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + picture_file_name) + ".png" + else: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + picture_file_name) + ".jpeg" + + if os.path.isfile(image_path): + return + + # Format Information + size_x = int(globvar_AFMdata.x_pixel) + size_y = int(globvar_AFMdata.y_pixel) + + globvar_AFMdata.speed = "{0:.1f}".format(globvar_AFMdata.speed) + + globvar_AFMdata.x_size = int(globvar_AFMdata.x_pixel) * \ + float(globvar_AFMdata.x_size)*math.pow(10,9) + globvar_AFMdata.y_size = int(globvar_AFMdata.y_pixel) * \ + float(globvar_AFMdata.y_size)*math.pow(10,9) + + mirror_x = False + mirror_y = False + + if globvar_AFMdata.x_size < 0: + mirror_x = True + if globvar_AFMdata.y_size < 0: + mirror_y = True + + globvar_AFMdata.x_size = "{0:.1f}".format(abs(globvar_AFMdata.x_size)) + globvar_AFMdata.y_size = "{0:.1f}".format(abs(globvar_AFMdata.y_size)) + + globvar_AFMdata.x_off = "{0:.1f}".format(float(globvar_AFMdata.x_off) * \ + math.pow(10,9)) + globvar_AFMdata.y_off = "{0:.1f}".format(float(globvar_AFMdata.y_off) * \ + math.pow(10,9)) + + # Read the position of the binary data. + with open(file_path, "rb") as sm4_file: # open file + + # Go to position in the file. + sm4_file.seek(data_off,0) + + # Go straight to numpy data (no buffering). + data = numpy.fromfile(sm4_file, dtype = numpy.int32, + count = size_x*size_y) + + # Check if the image really has the expected size. + # 'size_x*size_y'. + # old_y_size and old_y_pixel are needed to temporarily store + # the original size in y (nm and pixel). This is then used + # at the end to put back the original values for + # globvar_AFMdata.y_size and globvar_AFMdata.y_pixel, for the + # text in the thumbs. + data, old_y_size, old_y_pixel = check_image_properties(data, + globvar_AFMdata.datfile[-1]) + + # If there is some corrupt image the y value, which has been + # changed in check_image_properties, needs to be updated. + size_y = int(globvar_AFMdata.y_pixel) + + # First, transform the integers into floats. This is needed for all + # mathematical operations. + data = data.astype(float) + + # Average value + average = numpy.average(data) + + data = data * globvar_AFMdata.z_factor[-1] + # Calibrate the avergae value and write it into the globvar_AFMdata + # structure. + globvar_AFMdata.z_average = average * globvar_AFMdata.z_factor[-1] + + # Make now a 2D array. + data.shape = numpy.array([size_y, size_x]) + + # Mirror the data + if mirror_x: + data = numpy.fliplr(data) + if not mirror_y: + data = numpy.flipud(data) + + # Fitting + if line_fit(image_nr,direction): + data = linalg_line_fit(size_x, size_y, data) + + if plane_fit(image_nr,direction): + data = linalg_plane_fit(size_x, size_y, data) + + create_thumb_images(data, image_nr, picture_file_name, file_name) + + if old_y_size != "" and old_y_pixel != "": + globvar_AFMdata.y_size = old_y_size + globvar_AFMdata.y_pixel = old_y_pixel + + return True + + +def prepare_RHK_spektra(file_path, file_name, image_nr, data_off): + + picture_file_name = globvar_AFMdata.channel[-1].replace(" ","_") + "_" + \ + file_name + + # Add the specific number of the channel. + # Fill empty space with zeros. + if int(RHK_PositionCounter.position / 10) == 0: + picture_file_name = "000" + str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + elif int(RHK_PositionCounter.position / 10) < 10: + picture_file_name = "00" + str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + elif int(RHK_PositionCounter.position / 10) < 100: + picture_file_name = "0" + str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + else: + picture_file_name = str(RHK_PositionCounter.position) + \ + "_" + picture_file_name + RHK_PositionCounter.add() + + if globvar_ThumbPara.png: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + picture_file_name) + ".png" + else: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + picture_file_name) + ".jpeg" + + if os.path.isfile(image_path): + return + + # Format Text + globvar_AFMdata.spec_points = [0] + globvar_AFMdata.spec_points[0] = globvar_AFMdata.x_pixel + + globvar_AFMdata.spec_acquisition.append( + "{0:.6f}".format(globvar_AFMdata.speed / math.pow(10,6))) + globvar_AFMdata.spec_delay = [""] + globvar_AFMdata.spec_feedback = [""] + + # Read the position of the binary data. + size_x = int(globvar_AFMdata.x_pixel) + size_y = int(globvar_AFMdata.y_pixel) + + x_data_list = [] + y_data_list = [] + + x_data = [(x*abs(float(globvar_AFMdata.x_size))) + \ + float(globvar_AFMdata.x_off) for x in range(size_x)] + + with open(file_path, "rb") as sm4_file: # open file + + # Go to position in the file. + sm4_file.seek(data_off,0) + + # Go straight to numpy data (no buffering). + for i in range(size_y): + + x_data_list.append(x_data) + + y_data = numpy.fromfile(sm4_file, dtype = numpy.int32, + count = size_x) + + y_data = y_data.astype(float) + y_data = y_data*globvar_AFMdata.z_factor[-1] + y_data += globvar_AFMdata.y_off + y_data_list.append(y_data) + + create_thumb_spectra(x_data_list, + y_data_list, + 0, + picture_file_name, + image_path, + globvar_AFMdata.channel[-1]) + + return True diff --git a/AFM_thumbs/RHK.pyc b/AFM_thumbs/RHK.pyc new file mode 100755 index 0000000000000000000000000000000000000000..f2de91508e2853f69a228aeebe9aaba703c5c182 GIT binary patch literal 11732 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/SPECS_Nanonis.py b/AFM_thumbs/SPECS_Nanonis.py new file mode 100755 index 0000000..1456ef6 --- /dev/null +++ b/AFM_thumbs/SPECS_Nanonis.py @@ -0,0 +1,947 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import sys +import os +import numpy as np + +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_thumb_size_x +from AFM_thumbs.Variables import globvar_thumb_size_y +from AFM_thumbs.Variables import SPECS_Nanonis_images_must_exist +from AFM_thumbs.Variables import SPECS_Nanonis_spectroscopy_must_exist +from AFM_thumbs.Linalg import linalg_plane_fit +from AFM_thumbs.Linalg import linalg_line_fit +from AFM_thumbs.Linalg import check_image_properties +from AFM_thumbs.Thumbs import create_thumb_images +from AFM_thumbs.Thumbs import create_thumb_spectra +from AFM_thumbs.Initialize import initialize_AFM_data + +from AFM_thumbs.Channel import proceed_with +from AFM_thumbs.Channel import line_fit +from AFM_thumbs.Channel import plane_fit +from AFM_thumbs.Channel import rename_channel + + +# _________________________________________________________________ Definitions + +def is_SPECS_Nanonis_file(directory, files): + + list_directories = [] + + # A directroy is listed if there is at least one Nanonis file. + for filename in files: + file_name = os.path.join(directory, filename) + + if os.path.splitext(filename)[1] == SPECS_Nanonis_images_must_exist: + if os.path.isdir(directory): + list_directories.append(directory) + break + + if os.path.splitext(filename)[1] == SPECS_Nanonis_spectroscopy_must_exist: + if os.path.isdir(directory): + list_directories.append(directory) + break + + + return list_directories + + +# This is the definition, which stores diverse parameters from the header of +# an .sxm into the parameter class of AFM_thumbs. +def read_SPECS_Nanonis_image_data(nanonis_file): + + # # Print the entire header. + # nanonis_file_path = os.path.join(globvar_AFMdir.working_directory, nanonis_file) + # nanonis_file_p = open(nanonis_file_path, "rb") + # line = "" + # while line!=b':SCANIT_END:': + # line = nanonis_file_p.readline().rstrip() + # print(line) + # nanonis_file_p.close() + + initialize_AFM_data() + + # Open the Nanonis file. + nanonis_file_path = os.path.join(globvar_AFMdir.working_directory, + nanonis_file) + nanonis_file_p = open(nanonis_file_path, "rb") + + # Read until the end of the header and convert all into string. + line_ = "" + list_line = [] + while line_!=b':SCANIT_END:': + line_ = nanonis_file_p.readline().rstrip() + list_line.append(line_.decode("utf-8")) + + # Offset position of the data inside the sxm file. It is said that these + # are normally 4 bytes after the identifier ':SCANIT_END:'. However, + # the following seems to be the 'correct way'. + while nanonis_file_p.read(1)!=b'\x1a': + pass + assert nanonis_file_p.read(1)==b'\x04' + + # Note the offset and ... + data_offset = nanonis_file_p.tell() + # ... close the Nanonis file ... + nanonis_file_p.close() + + # Read now the header in 'list_line'. + for i in range(len(list_line)): + + if ":REC_DATE:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().strip() + globvar_AFMdata.date = line + if ":REC_TIME:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().strip() + globvar_AFMdata.date += ", " + line + if ":SCAN_FILE:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().strip() + globvar_AFMdata.datfile = [line] + if ":SCAN_RANGE:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().split(' ') + line = [x for x in line if x] + # The unit of x and y in nm. + x_size = float(line[0]) / 1e-9 + y_size = float(line[1]) / 1e-9 + globvar_AFMdata.x_size = "%.1f" % x_size + globvar_AFMdata.y_size = "%.1f" % y_size + if ":SCAN_PIXELS:" in list_line[i]: + line = list_line[i+1].rstrip().split(' ') + line = [x for x in line if x] + globvar_AFMdata.x_pixel = line[0] + globvar_AFMdata.y_pixel = line[1] + if ":SCAN_OFFSET:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().split(' ') + line = [x for x in line if x] + # The unit of x and y in nm. + x_off = float(line[0]) / 1e-9 + y_off = float(line[1]) / 1e-9 + globvar_AFMdata.x_off = "%.1f" % x_off + globvar_AFMdata.y_off = "%.1f" % y_off + if ":SCAN_ANGLE:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().strip() + globvar_AFMdata.angle = str(float(line)) + if ":SCAN_DIR:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().strip() + globvar_AFMdata.scan_updown = line + if ":SCAN_TIME:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().split(' ') + line = [x for x in line if x] + globvar_AFMdata.speed = float(line[0]) + # :ACQ_TIME: + # 255.6 + # :SCAN_TIME: + # 4.992E-1 4.992E-1 + if ":BIAS:" in list_line[i]: + i += 1 + line = list_line[i].rstrip().strip() + globvar_AFMdata.voltage = str(float(line)) + if ":Z-CONTROLLER:" in list_line[i]: + # :Z-CONTROLLER: + # Name on Setpoint P-gain I-gain T-const + # log Current 1 2.000E-10 A 2.937E-11 m 3.865E-7 m/s 7.599E-5 s + i += 2 + line = list_line[i].rstrip() + line = line.split(" ") + line = [x for x in line if x] + globvar_AFMdata.measurement_type = line[0] + # The unit of the feedback is needed further below + globvar_AFMdata.feedback = line[2] + # Remove the units of the gain + globvar_AFMdata.gain_prop = line[3].split(' ')[0] + globvar_AFMdata.gain_int = line[4].split(' ')[0] + #globvar_AFMdata.gain = line[5] + if ":DATA_INFO:" in list_line[i]: + # :DATA_INFO: + # Channel Name Unit Direction Calibration Offset + # 14 Z m both 1.400E-7 0.000E+0 + # 0C Current A both 3.000E-10 2.218E-12 + # 16 OC_D1_Phase deg both 1.800E+1 0.000E+0 + # 17 OC_D1_Amplitude m both 1.000E-9 0.000E+0 + # 18 OC_M1_Freq._Shift Hz both 7.812E+3 0.000E+0 + # 19 OC_M1_Excitation V both 1.000E-2 0.000E+0 + + # The channels with the following names are not supported. + # + # Bias + # Laser_power_mon. + # Laser_Setpoint + # Output_3 + # Output_4 + # X + # Y + # Output_8 + channels_not_supported = ["Bias", + "Laser_power_mon.", + "Laser_Setpoint", + "Output_3", + "Output_4", + "X", + "Y", + "Output_8"] + + i += 1 + line = list_line[i] + while True: + i += 1 + line = list_line[i].rstrip() + if line == '': + break + line = line.split(" ") + line = [x for x in line if x] + + # Channel name + channel_name = line[1] + # Just continue if a channel with a specific name is not + # supported. + if channel_name in channels_not_supported: + continue + + # Assign the correct channel names + if channel_name == "Current": + channel_name = "I" + if channel_name == "OC_D1_Phase": + channel_name = "Phase" + if channel_name == "OC_D1_Amplitude": + channel_name = "Amplitude" + if channel_name == "OC_M1_Freq._Shift": + channel_name = "df" + if channel_name == "OC_M1_Excitation": + channel_name = "Dissipation" + if channel_name == "KPFM": + channel_name = "Kelvin" + if channel_name == "KPFM_err": + channel_name = "KELVIN_ERR" + + globvar_AFMdata.scandir.append("forward") + globvar_AFMdata.scandir.append("backward") + # Put in 2x for forward and backward scanning direction. + rename_channel(channel_name) + rename_channel(channel_name) + globvar_AFMdata.unit.append(line[2]) + globvar_AFMdata.unit.append(line[2]) + globvar_AFMdata.z_calibration.append(line[4]) + globvar_AFMdata.z_calibration.append(line[4]) + globvar_AFMdata.z_offset.append(line[5]) + globvar_AFMdata.z_offset.append(line[5]) + + # AFM part + if ":Oscillation Control>Center Frequency (Hz):" in list_line[i]: + if "Frequency" in globvar_AFMdata.measurement_type: + i += 1 + line = list_line[i].rstrip().strip() + globvar_AFMdata.res_freq = line + if ":Oscillation Control>FrequencyShift (Hz):" in list_line[i]: + if "Frequency" in globvar_AFMdata.measurement_type: + i += 1 + line = list_line[i].rstrip().strip() + if ":Oscillation Control>Amplitude Setpoint (m):" in list_line[i]: + if "Frequency" in globvar_AFMdata.measurement_type: + i += 1 + line = list_line[i].rstrip().strip() + # Amplitude in nm! + amplitude = "%.1f" % (float(line) * 1e9) + if ":Oscillation Control>Input Calibration (m/V):" in list_line[i]: + if "Frequency" in globvar_AFMdata.measurement_type: + i += 1 + line = list_line[i].rstrip().strip() + # S_A in nm/V! + S_A = "%.1f" % (float(line) * 1e9) + + + # The amplitude info is a combination of the amplitude in nm AND the + # S_A calibration factor in nm/V. + if "Frequency" in globvar_AFMdata.measurement_type: + globvar_AFMdata.amplitude = amplitude + ", S_A: " + S_A + + # Preparation of some variables + # ============================= + # 1. We need to prepare the feedback variable. It can be the current + # (I, here in nA), force (here in nN) or df (here in Hz). + feedback = globvar_AFMdata.feedback.split(' ') + # For current and force + if feedback[-1] == 'A' or feedback[-1] == 'F': + globvar_AFMdata.feedback = str(float(feedback[0]) * 1e9) + # Everything in Hz etc. + else: + globvar_AFMdata.feedback = str(float(feedback[0])) + + # 2. The scan speed. Currently it is the time per line, however, we + # translate it into nm/s. Later, it is translated into frequency (Hz). + speed = float(globvar_AFMdata.x_size) / globvar_AFMdata.speed + globvar_AFMdata.speed = "%.2f" % speed + + # Return the offset, which is used in the definition + # 'prepare_Nanonis_images'. + return data_offset + + +# This is the definition, which prepares the image data of all channels. The +# data is then directly send to the definition, which prepares the thumbnails. +def prepare_SPECS_Nanonis_images(nanonis_file, data_offset): + + # Open the Nanonis file. Inside this file, all images can be found. So, + # the file remains open during the entire loading of the images. + nanonis_file_path = os.path.join(globvar_AFMdir.working_directory, + nanonis_file) + nanonis_file_p = open(nanonis_file_path, "rb") + + # Go through all channels and create the thumbnails. + for image_nr, channel in enumerate(globvar_AFMdata.channel): + + # The definition 'proceed_with' is 'connected' with the GUI of + # AFM_thumbs where one can choose if a channel of a specific + # scanning direction shall be represented in a pdf file or not. + if proceed_with(image_nr,globvar_AFMdata.scandir[image_nr]): + + # Prepare the file path. + pos = globvar_AFMdata.datfile[0].rfind('\\') + data_file_name = globvar_AFMdata.datfile[0][pos+1:] + + # The name of the thumbnail image, in a correct order. + image_name = data_file_name[:-4] + if image_name[2] == "_": + image_name = image_name[0:1]+"00"+image_name[1:] + if image_name[3] == "_": + image_name = image_name[0:1]+"0"+image_name[1:] + image_name = image_name + "_" + str(image_nr) + + # This is a code that is related to the option in the GUI, if the + # thumbs shall be saved as pngs or jpegs. + if globvar_ThumbPara.png: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".png" + else: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".jpeg" + + # If a thumb image exists continue with the next one (don't + # calculate a second time). + if os.path.isfile(image_path): + continue + + # x/y size of the image, taken from the parameter class. + size_x = int(globvar_AFMdata.x_pixel) + size_y = int(globvar_AFMdata.y_pixel) + + # Put the file pointer onto the correct position. One has to + # multipy by a factor of 4 because ... . + nanonis_file_p.seek(data_offset + image_nr*size_x*size_y*4) + + # Read the data block. It is 'big endian float 32' type of data. + # A block (an image) has the image size of 'size_x*size_y'. + data = np.fromfile(nanonis_file_p, + dtype = '>f4', + count = size_x*size_y) + # 'big endian float 32' : '>f4' + # 'little endian float 32': 'f8' + # 'little endian float 64': 'Input Calibration (m/V) " in line: + line = line.rstrip().split(' ') + sweep_A_cali = "%.2f" % (float(line[-1]) * 1e9) + if "Oscillation Control>Excitation (V) " in line: + line = line.rstrip().split(' ') + sweep_A_exi = "%.2f" % (float(line[-1]) * 1000.0) + + # NPC (NP charging) + # ================= + if FLAG_NPC: + if "Add_dz_start (m) " in line: + line = line.rstrip().split(' ') + spec_NPC_add_dz_start = "%.2f" % (float(line[-1]) * 1e9) + if "No_points " in line: + line = line.rstrip().split(' ') + spec_NPC_n_points = str(int(line[-1]) * 2) + if "DV_to_CPD (V) " in line: + line = line.rstrip().split(' ') + spec_NPC_dv_to_cpd = "%.2f" % (float(line[-1])) + if "CPD_measured (V) " in line: + line = line.rstrip().split(' ') + spec_NPC_cpd_measured = "%.2f" % (float(line[-1])) + if "Delay_for_CPD (ms) " in line: + line = line.rstrip().split(' ') + spec_NPC_cpd_delay = "%.1f" % (float(line[-1])) + if "Bias_voltage_range (V) " in line: + line = line.rstrip().split(' ') + spec_NPC_bias_range = "%.2f" % (float(line[-1])) + if "Z_averaging_time (s) " in line: + line = line.rstrip().split(' ') + spec_NPC_z_average_t = "%.2f" % (float(line[-1]) * 1000.0) + if "Z_offset (m) " in line: + line = line.rstrip().split(' ') + spec_NPC_z_off = "%.2f" % (float(line[-1]) * 1e9) + if "Integration_time (s) " in line: + line = line.rstrip().split(' ') + spec_NPC_t_integr = "%.2f" % (float(line[-1]) * 1000.0) + if "Settling_time (s) " in line or "Settling time (s) " in line: + line = line.rstrip().split(' ') + spec_NPC_t_settl = "%.2f" % (float(line[-1]) * 1000.0) + + + # FCA (force curve alignement method) + # =================================== + if FLAG_FCA: + if "No_points_curve " in line: + line = line.rstrip().split(' ') + spec_FCA_points_curve = line[-1] + if "Oscillation Control>Center Frequency (Hz) " in line: + line = line.rstrip().split(' ') + spec_FCA_f0 = "%.2f" % (float(line[-1]) / 1000.0) + if "Z_offset (m) " in line: + line = line.rstrip().split(' ') + spec_FCA_z_off = "%.1f" % (float(line[-1]) * 1e9) + if "Spring_constant (Hz) " in line: + line = line.rstrip().split(' ') + spec_FCA_k = "%.2f" % (float(line[-1])) + if "No_amplitude_values " in line: + line = line.rstrip().split(' ') + spec_FCA_A_no = line[-1] + if "Amplitude_start (V) " in line: + line = line.rstrip().split(' ') + spec_FCA_A_start = "%.2f" % (float(line[-1])) + if "Amplitude_change (V) " in line: + line = line.rstrip().split(' ') + spec_FCA_A_change = "%.2f" % (float(line[-1])) + if "Sweep_distance (m) " in line: + line = line.rstrip().split(' ') + spec_FCA_sweep_dist = "%.2f" % (float(line[-1]) * 1e9) + if "Time_acq_point (ms) " in line: + line = line.rstrip().split(' ') + spec_FCA_acquisition = "%.2f" % (float(line[-1]) / 1000.0) + if "Time_passed_loop" in line: + line = line.rstrip().split(' ') + spec_FCA_t_loop = "%.2f" % (float(line[-1])) + if "Time_passed_tot" in line: + line = line.rstrip().split(' ') + spec_FCA_t_tot = "%.2f" % (float(line[-1])) + + # It is not a Nanonis data file because the identifier '[DATA]' could not + # be found! + if not FLAG_real_dat_file: + return [], [] + + list_data = [] + for i, line in enumerate(data_file_p): + + # Do not consider empty lines. + if line[:-2] == "": + continue + + # Do not consider FCA specific identifiers. + if "loop_" in line.lower(): + continue + + line = line.rstrip().strip().split(' ') + + if i == 0: + for channel in line[1:]: + # We basically use always the same x values + unit = line[0].split(' ')[-1][1:-1] + globvar_AFMdata.spec_x_label.append(line[0][:-(len(unit)+2)]) + globvar_AFMdata.spec_x_unit.append(unit) + # The y values + unit = channel.split(' ')[-1][1:-1] + globvar_AFMdata.spec_y_label.append(channel[:-(len(unit)+2)]) + globvar_AFMdata.spec_y_unit.append(unit) + continue + + list_data.append(line) + + # Close the file. + data_file_p.close() + + list_X = [] + list_Y = [] + for i in range(len(list_data[0])-1): + list_x = [] + list_y = [] + for line in list_data: + list_x.append(float(line[0])) + list_y.append(float(line[i+1])) + list_X.append(list_x) + list_Y.append(list_y) + + nr_channels = len(list_data[0])-1 + nr_points = len(list_X[0]) + + # Preparation of text string for the thumbs + # ========================================= + + # Attention! + # ---------- + # We have to adapt to the 'old' way of SCALA doing... . However, we ceate + # our specific 'globvar_AFMdata.spec_other' variable, which contains all + # parameters. Preparing the text string already here is much more easy ... . + + globvar_AFMdata.spec_other = "" + + if 'date' in locals(): + globvar_AFMdata.spec_other += "-- " + date + " -- " + + # First the x, y, z position + spec_position = "" + if 'spec_pos_x' in locals(): + spec_position += spec_pos_x + "|" + if 'spec_pos_y' in locals(): + spec_position += spec_pos_y + "|" + if 'spec_pos_z' in locals(): + spec_position += spec_pos_z + else: + if globvar_AFMdata.spec_position != "": + spec_position = spec_position[:-1] + if 'spec_pos_z_off' in locals(): + spec_position += "(" + spec_pos_z_off + ")" + + globvar_AFMdata.spec_position = [spec_position] * nr_channels + + # Text for z spectroscopy + if FLAG_Z_SPEC: + globvar_AFMdata.spec_other += "Points: " + str(nr_points) + "nm, " + if 'spec_z_off' in locals(): + globvar_AFMdata.spec_other += "Z off: " + spec_z_off + "nm, " + if 'spec_z_dist' in locals(): + globvar_AFMdata.spec_other += "Z dist. range: " + spec_z_dist + "nm, " + if 'spec_z_filter' in locals(): + globvar_AFMdata.spec_other += "Filter: " + spec_z_filter + ", " + if 'spec_z_t_integr' in locals(): + globvar_AFMdata.spec_other += "t (integr): " + spec_z_t_integr + "ms, " + if 'spec_z_t_settl' in locals(): + globvar_AFMdata.spec_other += "t (settl): " + spec_z_t_settl + "ms, " + if 'spec_z_t_integr' in locals() and 'spec_z_t_settl': + spec_z_t_total = "%.2f" % ((float(spec_z_t_integr) + + float(spec_z_t_settl)) * + float(nr_points) / 1000.0) + globvar_AFMdata.spec_other += "t (tot): " + spec_z_t_total + "s, " + + # Text for U spectroscopy + if FLAG_U_SPEC: + globvar_AFMdata.spec_other += "Points: " + str(nr_points) + "nm, " + if 'spec_U_filter' in locals(): + globvar_AFMdata.spec_other += "Filter: " + spec_U_filter + ", " + if 'spec_U_t_integr' in locals(): + globvar_AFMdata.spec_other += "t (integr): " + spec_U_t_integr + "ms, " + if 'spec_U_t_settl' in locals(): + globvar_AFMdata.spec_other += "t (settl): " + spec_U_t_settl + "ms, " + if 'spec_U_t_integr' in locals() and 'spec_U_t_settl' in locals(): + spec_t_total = "%.2f" % ((float(spec_U_t_integr) + + float(spec_U_t_settl)) * + float(nr_points) / 1000.0) + globvar_AFMdata.spec_other += "t (tot): " + spec_t_total + "s, " + + # Text for U sweep + if FLAG_U_SWEEP: + if 'sweep_U_points' in locals(): + globvar_AFMdata.spec_other += "Points: " + sweep_U_points + ", " + if 'sweep_U_ini' in locals(): + globvar_AFMdata.spec_other += "U_ini: " + sweep_U_ini + "V, " + if 'sweep_U_lower_limit' in locals(): + globvar_AFMdata.spec_other += "U_low: " + sweep_U_lower_limit + "V, " + if 'sweep_U_upper_limit' in locals(): + globvar_AFMdata.spec_other += "U_up: " + sweep_U_upper_limit + "V, " + if 'sweep_U_step' in locals(): + globvar_AFMdata.spec_other += "U_step: " + sweep_U_step + "V, " + if 'sweep_U_controller' in locals(): + globvar_AFMdata.spec_other += "Controller: " + sweep_U_controller + ", " + if 'sweep_U_reset' in locals(): + globvar_AFMdata.spec_other += "Reset: " + sweep_U_reset + ", " + if 'sweep_U_t_integr' in locals(): + globvar_AFMdata.spec_other += "t (integr): " + sweep_U_t_integr + "ms, " + if 'sweep_U_t_settl' in locals(): + globvar_AFMdata.spec_other += "t (settl): " + sweep_U_t_settl + "ms, " + if 'sweep_U_t_integr' in locals() and 'sweep_U_t_settl' in locals() and 'sweep_U_points' in locals(): + sweep_t_total = "%.2f" % ((float(sweep_U_t_integr) + + float(sweep_U_t_settl)) * + float(sweep_U_points) / 1000.0) + globvar_AFMdata.spec_other += "t (tot): " + sweep_t_total + "s, " + + # Text for f0 sweep + if FLAG_f0_SPEC: + if 'sweep_points_curve' in locals(): + globvar_AFMdata.spec_other += "Points: " + sweep_points_curve + ", " + if 'sweep_f0' in locals(): + globvar_AFMdata.spec_other += "f0: " + sweep_f0 + "Hz, " + if 'sweep_Q' in locals(): + globvar_AFMdata.spec_other += "Q: " + sweep_Q + ", " + if 'sweep_phase' in locals(): + globvar_AFMdata.spec_other += "Phi: " + sweep_phase + "V, " + if 'sweep_A_exi_cal' in locals(): + globvar_AFMdata.spec_other += "A_exi_cal: " + sweep_A_exi_cal + "nm/mV, " + if 'sweep_A_cali' in locals(): + globvar_AFMdata.spec_other += "A_cali: " + sweep_A_cali + "nm/V, " + if 'sweep_A_exi' in locals(): + globvar_AFMdata.spec_other += "A_exi: " + sweep_A_exi + "mV" + + # Text for the NPC method + if FLAG_NPC: + if 'spec_NPC_n_points' in locals(): + globvar_AFMdata.spec_other += "Points: " + spec_NPC_n_points + ", " + if 'spec_NPC_add_dz_start' in locals(): + globvar_AFMdata.spec_other += "Add_z_start: " + spec_NPC_add_dz_start + "nm, " + if 'spec_NPC_dv_to_cpd' in locals(): + globvar_AFMdata.spec_other += "CPD-dV: " + spec_NPC_dv_to_cpd + "V, " + if 'spec_NPC_cpd_measured' in locals(): + globvar_AFMdata.spec_other += "CPD: " + spec_NPC_cpd_measured + "V, " + if 'spec_NPC_cpd_delay' in locals(): + globvar_AFMdata.spec_other += "t (CPD): " + spec_NPC_cpd_delay + "ms, " + if 'spec_NPC_bias_range' in locals(): + globvar_AFMdata.spec_other += "V range: " + spec_NPC_bias_range + "V, " + if 'spec_NPC_z_average_t' in locals(): + globvar_AFMdata.spec_other += "Z average t: " + spec_NPC_z_average_t + "ms, " + if 'spec_NPC_z_off' in locals(): + globvar_AFMdata.spec_other += "Z off: " + spec_NPC_z_off + "nm, " + if 'spec_NPC_t_integr' in locals(): + globvar_AFMdata.spec_other += "t (integr): " + spec_NPC_t_integr + "ms, " + if 'spec_NPC_t_settl' in locals(): + globvar_AFMdata.spec_other += "t (settl): " + spec_NPC_t_settl + "ms, " + if 'spec_NPC_t_integr' in locals() and 'spec_NPC_n_points' in locals() and 'spec_NPC_t_settl' in locals(): + spec_NPC_t_total = "%.2f" % ((float(spec_NPC_t_integr) + + float(spec_NPC_t_settl)) * + float(spec_NPC_n_points) / 1000.0) + globvar_AFMdata.spec_other += "t (tot): " + spec_NPC_t_total + "s, " + + # Text for the FCA method + if FLAG_FCA: + if 'spec_FCA_points_curve' in locals(): + globvar_AFMdata.spec_other += "Points/curve: " + spec_FCA_points_curve + ", " + if 'spec_FCA_k' in locals(): + globvar_AFMdata.spec_other += "k: " + spec_FCA_k + "N/m, " + if 'spec_FCA_f0' in locals(): + globvar_AFMdata.spec_other += "f0: " + spec_FCA_f0 + "Hz, " + if 'spec_FCA_A_no' in locals(): + globvar_AFMdata.spec_other += "No. Ampls: " + spec_FCA_A_no + ", " + if 'spec_FCA_A_start' in locals(): + globvar_AFMdata.spec_other += "A_start: " + spec_FCA_A_start + "V, " + if 'spec_FCA_A_change' in locals(): + globvar_AFMdata.spec_other += "A_change: " + spec_FCA_A_change + "V, " + if 'spec_FCA_z_off' in locals(): + globvar_AFMdata.spec_other += "Z_offset: " + spec_FCA_z_off + "nm, " + if 'spec_FCA_sweep_dist' in locals(): + globvar_AFMdata.spec_other += "Dist: " + spec_FCA_sweep_dist + "nm, " + if 'spec_FCA_t_loop' in locals(): + globvar_AFMdata.spec_other += "t (exp): " + spec_FCA_t_loop + "min, " + if 'spec_FCA_t_tot' in locals(): + globvar_AFMdata.spec_other += "t (tot): " + spec_FCA_t_tot + "min, " + + #print(nanonis_file, + # globvar_AFMdata.date, + # globvar_AFMdata.spec_files, + # globvar_AFMdata.spec_x_label, + # globvar_AFMdata.spec_x_unit, + # globvar_AFMdata.spec_y_label, + # globvar_AFMdata.spec_y_unit, + # globvar_AFMdata.spec_y_factor, + # globvar_AFMdata.spec_points, + # globvar_AFMdata.spec_feedback, + # globvar_AFMdata.spec_acquisition, + # globvar_AFMdata.spec_time, + # globvar_AFMdata.spec_position, + # globvar_AFMdata.spec_delay, + # globvar_AFMdata.sweep_f0, + # globvar_AFMdata.sweep_Q, + # globvar_AFMdata.sweep_phase, + # globvar_AFMdata.sweep_A_exec) + + return list_X, list_Y + + + +# This is the definition, which prepares the spectra data. The +# data is then directly send to the definition, which prepares the thumbnails. +def prepare_SPECS_Nanonis_spectra_curves(nanonis_file): + + initialize_AFM_data() + + data_file_name = nanonis_file + data_file = os.path.join(globvar_AFMdir.working_directory,data_file_name) + + list_X, list_Y = read_SPECS_Nanonis_spectra_data(data_file) + if list_X == [] or list_Y == []: + return False + + i = 0 + for list_x, list_y in zip(list_X, list_Y): + + image_name, file_extension = os.path.splitext(nanonis_file) + # There has to be an 's', which is used to identify the thumb image as + # an spectroscopy thumb image! + image_name = image_name + "_" + "s%02d" % (i) + + if globvar_ThumbPara.png: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".png" + else: + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, + image_name) + ".jpeg" + + if os.path.isfile(image_path): + return True + + create_thumb_spectra([list_x], + [list_y], + i, + image_name, + image_path, + globvar_AFMdata.spec_y_label[i]) + + i += 1 + + return True diff --git a/AFM_thumbs/SPECS_Nanonis.pyc b/AFM_thumbs/SPECS_Nanonis.pyc new file mode 100755 index 0000000000000000000000000000000000000000..3da32102030a8e78459e7142645024bbc73f3a58 GIT binary patch literal 18843 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 Path: +# D:\Session_test\Session_first_time_test +# :NanonisMain>SW Version: +# Generic 5e +# :NanonisMain>UI Release: +# 10278 +# :NanonisMain>RT Release: +# 10278 +# :NanonisMain>RT Frequency (Hz): +# 20E+3 +# :NanonisMain>Signals Oversampling: +# 10 +# :NanonisMain>Acquisition Period (s): +# 20E-3 +# :NanonisMain>Animations Period (s): +# 20E-3 +# :NanonisMain>Indicators Period (s): +# 300E-3 +# :NanonisMain>Measurements Period (s): +# 500E-3 +# :Bias>Bias (V): +# 2E+0 +# :Bias>Calibration (V/V): +# 1E+0 +# :Bias>Offset (V): +# 0E+0 +# :Current>Current (A): +# 50.033E-12 +# :Current>Calibration (A/V): +# 5E-9 +# :Current>Offset (A): +# 0E+0 +# :Current>Gain: +# Low +# :Piezo Configuration>Active Calib.: +# Default +# :Piezo Configuration>Calib. X (m/V): +# 6E-9 +# :Piezo Configuration>Calib. Y (m/V): +# 6E-9 +# :Piezo Configuration>Calib. Z (m/V): +# -6E-9 +# :Piezo Configuration>HV Gain X: +# 15 +# :Piezo Configuration>HV Gain Y: +# 15 +# :Piezo Configuration>HV Gain Z: +# 15 +# :Piezo Configuration>Tilt X (deg): +# 0 +# :Piezo Configuration>Tilt Y (deg): +# 0 +# :Piezo Configuration>Curvature radius X (m): +# Inf +# :Piezo Configuration>Curvature radius Y (m): +# Inf +# :Piezo Configuration>2nd order corr X (V/m^2): +# 0E+0 +# :Piezo Configuration>2nd order corr Y (V/m^2): +# 0E+0 +# :Piezo Configuration>Drift X (m/s): +# 0E+0 +# :Piezo Configuration>Drift Y (m/s): +# 0E+0 +# :Piezo Configuration>Drift Z (m/s): +# 0E+0 +# :Piezo Configuration>Drift correction status (on/off): +# FALSE +# :Z-Controller>Z (m): +# 39.1035E-9 +# :Z-Controller>Controller name: +# log Current +# :Z-Controller>Controller status: +# ON +# :Z-Controller>Setpoint: +# 50E-12 +# :Z-Controller>Setpoint unit: +# A +# :Z-Controller>P gain: +# 200E-12 +# :Z-Controller>I gain: +# 200E-9 +# :Z-Controller>Time const (s): +# 1E-3 +# :Z-Controller>TipLift (m): +# 0E+0 +# :Z-Controller>Switch off delay (s): +# 0E+0 +# :Oscillation Control>differential input: +# FALSE +# :Oscillation Control>input 1/10: +# FALSE +# :Oscillation Control>Input Calibration (m/V): +# 1E-6 +# :Oscillation Control>Input Range (m): +# 20.2162E-9 +# :Oscillation Control>Center Frequency (Hz): +# 200E+3 +# :Oscillation Control>Range (Hz): +# 9.53674E+0 +# :Oscillation Control>Demod 1 Input: +# 1 +# :Oscillation Control>Demod 2 Input: +# 1 +# :Oscillation Control>Demod 3 Input: +# 1 +# :Oscillation Control>Demod 4 Input: +# 1 +# :Oscillation Control>Demod 1 Frequency: +# 1 +# :Oscillation Control>Demod 2 Frequency: +# 1 +# :Oscillation Control>Demod 3 Frequency: +# 1 +# :Oscillation Control>Demod 4 Frequency: +# 1 +# :Oscillation Control>Demod 1 Reference Phase (deg): +# 0E+0 +# :Oscillation Control>Demod 2 Reference Phase (deg): +# 0E+0 +# :Oscillation Control>Demod 3 Reference Phase (deg): +# 0E+0 +# :Oscillation Control>Demod 4 Reference Phase (deg): +# 0E+0 +# :Oscillation Control>Demod 1 Cut off frq (Hz): +# 1.55k +# :Oscillation Control>Demod 2 Cut off frq (Hz): +# 1.55k +# :Oscillation Control>Demod 3 Cut off frq (Hz): +# 1.55k +# :Oscillation Control>Demod 4 Cut off frq (Hz): +# 1.55k +# :Oscillation Control>Demod 1 Harmonic: +# 1 +# :Oscillation Control>Demod 2 Harmonic: +# 1 +# :Oscillation Control>Demod 3 Harmonic: +# 1 +# :Oscillation Control>Demod 4 Harmonic: +# 1 +# :Oscillation Control>Demod 1 Filter Order: +# 2 +# :Oscillation Control>Demod 2 Filter Order: +# 2 +# :Oscillation Control>Demod 3 Filter Order: +# 2 +# :Oscillation Control>Demod 4 Filter Order: +# 2 +# :Oscillation Control>Phase P gain (Hz/rad): +# 151.8E-3 +# :Oscillation Control>Phase I gain (Hz/rad/s): +# 755.511E-3 +# :Oscillation Control>Phase controller on: +# FALSE +# :Oscillation Control>FrequencyShift (Hz): +# 0E+0 +# :Oscillation Control>Amplitude Setpoint (m): +# 1E-9 +# :Oscillation Control>Amplitude P gain (V/nm): +# 1.41747E+3 +# :Oscillation Control>Amplitude I gain (V/nm/s): +# 1.32194E+3 +# :Oscillation Control>Amplitude controller on: +# FALSE +# :Oscillation Control>Excitation (V): +# 1E-3 +# :Oscillation Control>Output Ampl. Range (V): +# 10 +# :Oscillation Control>output off: +# FALSE +# :Oscillation Control>output add: +# TRUE +# :Oscillation Control>PLL-Setup Q-Factor: +# 14.284E+3 +# :Oscillation Control>PLL-Setup Demod. Bandwidth Amp (Hz): +# 78.7927E-6 +# :Oscillation Control>PLL-Setup Demod. Bandwidth Pha (Hz): +# 8.69749E+0 +# :Oscillation Control>PLL-Setup amplitude/excitation (m/V): +# 7.94E-9 +# :Scan>Scanfield: +# 0E+0;0E+0;20E-9;20E-9;0E+0 +# :Scan>series name: +# Test +# :Scan>channels: +# Current (A);Z (m) +# :Scan>pixels/line: +# 256 +# :Scan>lines: +# 256 +# :Scan>speed forw. (m/s): +# 312.5E-9 +# :Scan>speed backw. (m/s): +# 312.5E-9 +# :DATA_INFO: +# Channel Name Unit Direction Calibration Offset +# 14 Z m both -9.000E-8 0.000E+0 +# 0 Current A both 5.000E-9 0.000E+0 +# +# :SCANIT_END: + +# Another one + +# :NANONIS_VERSION: +# 2 +# :SCANIT_TYPE: +# FLOAT MSBFIRST +# :REC_DATE: +# 05.02.2021 +# :REC_TIME: +# 19:40:42 +# :REC_TEMP: +# 290.0000000000 +# :ACQ_TIME: +# 288.5 +# :SCAN_PIXELS: +# 512 512 +# :SCAN_FILE: +# D:\Data\sessions_Ag001\2021-02-03_cycle_13\m_0086.sxm +# :SCAN_TIME: +# 5.120E-1 5.120E-1 +# :SCAN_RANGE: +# 2.500000E-7 2.500000E-7 +# :SCAN_OFFSET: +# 1.235544E-7 2.410663E-7 +# :SCAN_ANGLE: +# 0.000E+0 +# :SCAN_DIR: +# down +# :BIAS: +# 5.321E-1 +# :Z-CONTROLLER: +# Name on Setpoint P-gain I-gain T-const +# Frequency (neg) 1 -4.500E+1 Hz 6.983E-11 m/Hz 2.643E-8 m/Hz/s 2.643E-3 s +# :COMMENT: +# +# :NanonisMain>Session Path: +# D:\Data\sessions_Ag001\2021-02-03_cycle_13 +# :NanonisMain>SW Version: +# Generic 5e +# :NanonisMain>UI Release: +# 10278 +# :NanonisMain>RT Release: +# 10278 +# :NanonisMain>RT Frequency (Hz): +# 20E+3 +# :NanonisMain>Signals Oversampling: +# 10 +# :NanonisMain>Acquisition Period (s): +# 20E-3 +# :NanonisMain>Animations Period (s): +# 20E-3 +# :NanonisMain>Indicators Period (s): +# 300E-3 +# :NanonisMain>Measurements Period (s): +# 10E-3 +# :Bias>Bias (V): +# 532.11E-3 +# :Bias>Calibration (V/V): +# 1E+0 +# :Bias>Offset (V): +# 0E+0 +# :Current>Current (A): +# -132.953E-15 +# :Current>Calibration (A/V): +# 300E-12 +# :Current>Offset (A): +# 2.2182E-12 +# :Current>Gain: +# High +# :Piezo Configuration>Active Calib.: +# Default +# :Piezo Configuration>Calib. X (m/V): +# 10E-9 +# :Piezo Configuration>Calib. Y (m/V): +# 10E-9 +# :Piezo Configuration>Calib. Z (m/V): +# 10E-9 +# :Piezo Configuration>HV Gain X: +# 14 +# :Piezo Configuration>HV Gain Y: +# 14 +# :Piezo Configuration>HV Gain Z: +# 14 +# :Piezo Configuration>Tilt X (deg): +# 14.5234 +# :Piezo Configuration>Tilt Y (deg): +# 2.32116 +# :Piezo Configuration>Curvature radius X (m): +# Inf +# :Piezo Configuration>Curvature radius Y (m): +# Inf +# :Piezo Configuration>2nd order corr X (V/m^2): +# 0E+0 +# :Piezo Configuration>2nd order corr Y (V/m^2): +# 0E+0 +# :Piezo Configuration>Drift X (m/s): +# 0E+0 +# :Piezo Configuration>Drift Y (m/s): +# 0E+0 +# :Piezo Configuration>Drift Z (m/s): +# 0E+0 +# :Piezo Configuration>Drift correction status (on/off): +# FALSE +# :Z-Controller>Z (m): +# 136.55E-9 +# :Z-Controller>Controller name: +# Frequency (neg) +# :Z-Controller>Controller status: +# ON +# :Z-Controller>Setpoint: +# -45E+0 +# :Z-Controller>Setpoint unit: +# Hz +# :Z-Controller>P gain: +# 69.8291E-12 +# :Z-Controller>I gain: +# 26.4252E-9 +# :Z-Controller>Time const (s): +# 2.64252E-3 +# :Z-Controller>TipLift (m): +# 0E+0 +# :Z-Controller>Switch off delay (s): +# 0E+0 +# :Oscillation Control>differential input: +# TRUE +# :Oscillation Control>input 1/10: +# FALSE +# :Oscillation Control>Input Calibration (m/V): +# 10E-9 +# :Oscillation Control>Input Range (m): +# 10E-9 +# :Oscillation Control>Center Frequency (Hz): +# 311.101E+3 +# :Oscillation Control>Range (Hz): +# 78.125E+3 +# :Oscillation Control>Demod 1 Input: +# 1 +# :Oscillation Control>Demod 2 Input: +# 1 +# :Oscillation Control>Demod 3 Input: +# 1 +# :Oscillation Control>Demod 4 Input: +# 1 +# :Oscillation Control>Demod 1 Frequency: +# 1 +# :Oscillation Control>Demod 2 Frequency: +# 1 +# :Oscillation Control>Demod 3 Frequency: +# 1 +# :Oscillation Control>Demod 4 Frequency: +# 1 +# :Oscillation Control>Demod 1 Reference Phase (deg): +# 88.88E+0 +# :Oscillation Control>Demod 2 Reference Phase (deg): +# 0E+0 +# :Oscillation Control>Demod 3 Reference Phase (deg): +# 0E+0 +# :Oscillation Control>Demod 4 Reference Phase (deg): +# 0E+0 +# :Oscillation Control>Demod 1 Cut off frq (Hz): +# 3.11k +# :Oscillation Control>Demod 2 Cut off frq (Hz): +# 1.55k +# :Oscillation Control>Demod 3 Cut off frq (Hz): +# 1.55k +# :Oscillation Control>Demod 4 Cut off frq (Hz): +# 1.55k +# :Oscillation Control>Demod 1 Harmonic: +# 1 +# :Oscillation Control>Demod 2 Harmonic: +# 1 +# :Oscillation Control>Demod 3 Harmonic: +# 1 +# :Oscillation Control>Demod 4 Harmonic: +# 1 +# :Oscillation Control>Demod 1 Filter Order: +# 2 +# :Oscillation Control>Demod 2 Filter Order: +# 2 +# :Oscillation Control>Demod 3 Filter Order: +# 2 +# :Oscillation Control>Demod 4 Filter Order: +# 2 +# :Oscillation Control>Phase P gain (Hz/rad): +# 1.67285E+0 +# :Oscillation Control>Phase I gain (Hz/rad/s): +# 57.6281E+0 +# :Oscillation Control>Phase controller on: +# TRUE +# :Oscillation Control>FrequencyShift (Hz): +# -44.9015E+0 +# :Oscillation Control>Amplitude Setpoint (m): +# 300E-12 +# :Oscillation Control>Amplitude P gain (V/nm): +# 12.4425E+6 +# :Oscillation Control>Amplitude I gain (V/nm/s): +# 428.632E+6 +# :Oscillation Control>Amplitude controller on: +# TRUE +# :Oscillation Control>Excitation (V): +# 408.923E-6 +# :Oscillation Control>Output Ampl. Range (V): +# 0.1 +# :Oscillation Control>output off: +# TRUE +# :Oscillation Control>output add: +# FALSE +# :Oscillation Control>PLL-Setup Q-Factor: +# 27.721E+3 +# :Oscillation Control>PLL-Setup Demod. Bandwidth Amp (Hz): +# 392.6E+0 +# :Oscillation Control>PLL-Setup Demod. Bandwidth Pha (Hz): +# 95.847E+0 +# :Oscillation Control>PLL-Setup amplitude/excitation (m/V): +# 753.229E-9 +# :Scan>Scanfield: +# 123.554E-9;241.066E-9;250E-9;250E-9;0E+0 +# :Scan>series name: +# m_ +# :Scan>channels: +# Current (A);Z (m);OC D1 Amplitude (m);OC M1 Freq. Shift (Hz);OC M1 Excitation (V) +# :Scan>pixels/line: +# 512 +# :Scan>lines: +# 512 +# :Scan>speed forw. (m/s): +# 488.281E-9 +# :Scan>speed backw. (m/s): +# 488.281E-9 +# :Bias Spectroscopy>Sweep Start (V): +# -5E+0 +# :Bias Spectroscopy>Sweep End (V): +# 5E+0 +# :Bias Spectroscopy>Num Pixel: +# 256 +# :Bias Spectroscopy>Z Avg time (s): +# 50E-3 +# :Bias Spectroscopy>Z offset (m): +# 0E+0 +# :Bias Spectroscopy>1st Settling time (s): +# 5E-3 +# :Bias Spectroscopy>Settling time (s): +# 200E-6 +# :Bias Spectroscopy>Integration time (s): +# 100E-6 +# :Bias Spectroscopy>End Settling time (s): +# 5E-3 +# :Bias Spectroscopy>Z control time (s): +# 200E-3 +# :Bias Spectroscopy>Max Slew rate (V/s): +# Inf +# :Bias Spectroscopy>backward sweep: +# FALSE +# :Bias Spectroscopy>Z-controller hold: +# TRUE +# :Bias Spectroscopy>Number of sweeps: +# 1 +# :Bias Spectroscopy>Channels: +# Current (A) +# :Bias Spectroscopy>Reset Bias: +# TRUE +# :Bias Spectroscopy>Record final Z: +# FALSE +# :Bias Spectroscopy>Lock-In run: +# FALSE +# :Z Spectroscopy>Initial Z-offset (m): +# 1E-9 +# :Z Spectroscopy>Sweep distance (m): +# -7E-9 +# :Z Spectroscopy>Num Pixel: +# 256 +# :Z Spectroscopy>Z Avg time (s): +# 50E-3 +# :Z Spectroscopy>1st Settling time (s): +# 5E-3 +# :Z Spectroscopy>Settling time (s): +# 200E-6 +# :Z Spectroscopy>Integration time (s): +# 100E-6 +# :Z Spectroscopy>End Settling time (s): +# 5E-3 +# :Z Spectroscopy>Z control time (s): +# 200E-3 +# :Z Spectroscopy>Max Slew rate (V/s): +# Inf +# :Z Spectroscopy>backward sweep: +# TRUE +# :Z Spectroscopy>Number of sweeps: +# 1 +# :Z Spectroscopy>Channels: +# Current (A) +# :Z Spectroscopy>Time between fwd/bwd (s): +# 0E+0 +# :Z Spectroscopy>Record final Z: +# FALSE +# :Z Spectroscopy>Lock-In run: +# FALSE +# :Z Spectroscopy>Reset Z: +# TRUE +# :DATA_INFO: +# Channel Name Unit Direction Calibration Offset +# 14 Z m both 1.400E-7 0.000E+0 +# 0 Current A both 3.000E-10 2.218E-12 +# 17 OC_D1_Amplitude m both 1.000E-9 0.000E+0 +# 18 OC_M1_Freq._Shift Hz both 7.812E+3 0.000E+0 +# 19 OC_M1_Excitation V both 1.000E-2 0.000E+0 +# +# :SCANIT_END: diff --git a/AFM_thumbs/Thumbs.py b/AFM_thumbs/Thumbs.py new file mode 100755 index 0000000..ab806e7 --- /dev/null +++ b/AFM_thumbs/Thumbs.py @@ -0,0 +1,463 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### +# +# This is part of the python program 'AFM_thumbs'. Please, read the +# full licence text and other comments in the file 'AFM_thumbs.py' +# +# Dr. Clemens Barth (barth@root-1.de), project manager. +# +# DO NOT REMOVE THIS PREAMBLE !!! +# + +import sys +import os +import numpy as np +import re + +# The following is a bit confusing but needed for crontab and ssh under Linux: +# Matplotlib needs an X-Server, which does not exist when doing, e.g., ssh. +# In the following we ask if the DISPLAY variable of the Linux system is set. +# If this is not the case then we tell Python to do something special for +# matplotlib (use of 'Agg') +# +# From: "http://stackoverflow.com/questions/4931376/ +# generating-matplotlib-graphs-without-a-running-x-server" +# Other solution: matplotlib API, see "http://www.dalkescientific.com/writings/ +# diary/archive/2005/04/23/matplotlib_without_gui.html" +if sys.platform == "linux2": + environ = os.environ + if "DISPLAY" not in environ: + import matplotlib as mpl + mpl.use('Agg') +import matplotlib.pyplot as plt +import matplotlib.lines as mpllines +from matplotlib.colors import LinearSegmentedColormap + +from AFM_thumbs.Variables import globvar_AFMdata +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_thumb_size_x +from AFM_thumbs.Variables import globvar_thumb_size_y +from AFM_thumbs.Variables import globvar_thumb_text_width +from AFM_thumbs.Variables import ID_abbreviations +from AFM_thumbs.Channel import select_color +from AFM_thumbs.Channel import invert +from AFM_thumbs.Colour import reverse_colourmap + +# _________________________________________________________________ Definitions + +def create_thumb_images(data, image_nr, image_name, data_file_name): + + # If there is a meaningful number in 'globvar_ThumbPara.rms': + if re.match("^\d+?\.\d+?$", globvar_ThumbPara.rms) != None: + + # We reshape the array first because we can then better analyze the + # data for the contrast adjustment via the rms value. + datar = np.reshape(data, data.size) + + # If there are regions in the image that are on the exact same value + # then discard them from the statistics analysis! This happens when, + # e.g., Nanonis images were not stored until the end of a scanning + # frame. + where = np.where(np.diff(datar) == 0) + # At least the length of a scanning line. + if len(where[0]) > float(globvar_AFMdata.x_pixel): + datar = np.delete(datar, where) + + # Put the rms value into a float. The factor of 2.0 is to adapt old + # values. + rms = abs(float(globvar_ThumbPara.rms)) * 2.0 + # Average value of the data array + aver = np.average(datar) + # Substrat the average value from the data and consider only the + # the absolute deviations from the average. + sub = np.abs(np.subtract(datar, aver)) + # From the absolute deviations, calculate the mean and max value. + sub_aver = np.average(sub) + sub_max = np.max(sub) + + # Are there any spikes, so, values that overpass by a factor of 30? + index = np.argwhere(sub > 30.0 * sub_aver) + if index.size > 0: + # We reduce the rms value by a factor of 2.0. + rms = rms / 2.0 + #print(image_nr, image_name, len(index)) + + # Cut the data on the top and bottom. + data = np.ma.clip(data, aver-sub_aver*rms, aver+sub_aver*rms) + + # This deaktivates the interactive pyplot frame + # plt.ioff() + + fig = plt.figure(figsize=(globvar_thumb_size_x, globvar_thumb_size_y)) + frame = plt.subplot(111) + + # Positioning of the image + plt.subplots_adjust(left=0.08, bottom=None, + right=0.99, top=1.1, + wspace=None, hspace=None) + + # Image is put in + try: + float(globvar_AFMdata.x_size) + except ValueError: + globvar_AFMdata.x_size = "-100.0" + + try: + float(globvar_AFMdata.y_size) + except ValueError: + globvar_AFMdata.y_size = "-100.0" + + imgage = frame.imshow(data,extent=[0,abs(float(globvar_AFMdata.x_size)), + 0,abs(float(globvar_AFMdata.y_size))]) + + # What kind of color scale do we have? + # Is it a pre-definied color from matplotlib, then it must be a string. + if type(select_color(image_nr, globvar_AFMdata.scandir[image_nr])) is str: + colormap = select_color(image_nr, globvar_AFMdata.scandir[image_nr]) + + if invert(image_nr,globvar_AFMdata.scandir[image_nr]): + colormap = reverse_colourmap("ListedColormap", colormap) + + # If it is not a string, then it must be a color definied by ourselves, + # so go to here and transform this linear segment into a colormap. + else: + colormap = LinearSegmentedColormap("Colormap",select_color(image_nr, + globvar_AFMdata.scandir[image_nr])) + + if invert(image_nr,globvar_AFMdata.scandir[image_nr]): + colormap = reverse_colourmap("LinearSegmentedColormap", colormap) + + # Color scale + imgage.set_cmap(colormap) + + if globvar_ThumbPara.peek: + imgage.set_clim(vmin=np.amin(data), vmax=np.amax(data)) + + # The colorbar + colorbar = fig.colorbar(imgage, shrink=0.65, aspect=30) + for t in colorbar.ax.get_yticklabels(): + t.set_fontsize('x-small') + + # The ticks and the size of the labels + plt.xticks(size = 'x-small') + plt.yticks(size = 'x-small') + + # The ticks and their orientation + # ... at the bottom + lines = frame.get_xticklines() + labels = frame.get_xticklabels() + for line in lines: + line.set_marker(mpllines.TICKDOWN) + for label in labels: + label.set_y(-0.02) + # ... on the left + lines = frame.get_yticklines() + labels = frame.get_yticklabels() + for line in lines: + line.set_marker(mpllines.TICKLEFT) + for label in labels: + label.set_x(-0.02) + + # Some text into the figure + # 1. Scanning direction to the bottom right + if globvar_AFMdata.scandir[image_nr] == "forward": + fig.text(0.83, 0.17, "forward", fontsize=10) + if globvar_AFMdata.scandir[image_nr] == "backward": + fig.text(0.83, 0.17, "backward", fontsize=10) + + # 2. Channel to the top right + fig.text(0.83, 0.95, + globvar_AFMdata.channel[image_nr] + " (" + \ + globvar_AFMdata.unit[image_nr] + ")", + fontsize=11) + + # 3. Text with parameters below the image + fig.text(0.035 + float(globvar_ThumbPara.text_x), + 0.015 + float(globvar_ThumbPara.text_y), + image_text(image_name), + fontname=globvar_ThumbPara.font, + size=int(globvar_ThumbPara.text_size)) + + # 4. Average value below color scale + data_average = globvar_AFMdata.z_average + data_average = str(data_average) + data_average = data_average[:data_average.find(".")+2] + fig.text(0.83, 0.2, + "Aver. (raw)\n" + data_average + " (" + \ + globvar_AFMdata.unit[image_nr] + ")", + fontsize=10) + + # Save image now ! + image_path = os.path.join(globvar_AFMdir.thumbnail_directory, image_name) + + if globvar_ThumbPara.png: + image_path=image_path+".png" + else: + image_path=image_path+".jpeg" + + plt.savefig(image_path, dpi=int(globvar_ThumbPara.res)) + + #plt.close('all') + plt.close(fig) + plt.clf() + + +def image_text(image_name): + + text_string = image_name + ", " + + if globvar_ThumbPara.date and globvar_AFMdata.date != "": + text_string += "--"+globvar_AFMdata.date+"--, " + if globvar_ThumbPara.sizenm and globvar_AFMdata.x_size != "" and \ + globvar_AFMdata.y_size != "": + text_string += "Size: " + globvar_AFMdata.x_size + "x" + \ + globvar_AFMdata.y_size + ", " + if globvar_ThumbPara.sizepx and globvar_AFMdata.x_pixel != "" and \ + globvar_AFMdata.y_pixel != "": + text_string += "Pixl: " + globvar_AFMdata.x_pixel + "x" + \ + globvar_AFMdata.y_pixel + ", " + if globvar_ThumbPara.offset and globvar_AFMdata.x_off != "" and \ + globvar_AFMdata.y_off != "": + text_string += "Off: " + globvar_AFMdata.x_off + "x" + \ + globvar_AFMdata.y_off + ", " + # SPECS Nanonis + # ============= + # So far, there is no option(button). This needs to be implemented in future. + if globvar_AFMdata.res_freq != "": + text_string += "f0: " + globvar_AFMdata.res_freq + ", " + if globvar_ThumbPara.gain and globvar_AFMdata.gain != "": + text_string += "Gain: " + globvar_AFMdata.gain + ", " + if globvar_ThumbPara.gain and globvar_AFMdata.gain_int != "": + text_string += "IGain: " + globvar_AFMdata.gain_int + ", " + if globvar_ThumbPara.gain and globvar_AFMdata.gain_prop != "": + text_string += "PGain: " + globvar_AFMdata.gain_prop + ", " + if globvar_ThumbPara.gain and globvar_AFMdata.gain_signal != "": + text_string += "SigGain: " + globvar_AFMdata.gain_signal + ", " + if globvar_ThumbPara.gain and globvar_AFMdata.gain_xy != "": + text_string += "XYGain: " + globvar_AFMdata.gain_xy + ", " + if globvar_ThumbPara.gain and globvar_AFMdata.gain_z != "": + text_string += "ZGain: " + globvar_AFMdata.gain_z + ", " + + # SPECS Nanonis + # ============= + # So far, there is no option (button). This needs to be implemented + # in future. + if globvar_AFMdata.scan_updown != "": + text_string += globvar_AFMdata.scan_updown.capitalize() + " scan, " + if globvar_ThumbPara.speed and globvar_AFMdata.speed != "": + # For Dulcinea + if " Hz" in globvar_AFMdata.speed: + speed = globvar_AFMdata.speed + text_string += speed + # Otherwise: we now use the scan frequency as a speed because it is + # more readable. (2021-02-05) + else: + speed = float(globvar_AFMdata.speed) / float(globvar_AFMdata.x_size) + text_string += "Speed: %.2f" % speed + ", " + if globvar_ThumbPara.ampl and globvar_AFMdata.amplitude != "": + text_string += "Ampl: " + globvar_AFMdata.amplitude + ", " + if globvar_ThumbPara.angle and globvar_AFMdata.angle != "": + text_string += "Phi: " + globvar_AFMdata.angle + ", " + # Change 2017-06-25 + # 1. Ugap and Feedback are listed at the end! + if globvar_ThumbPara.voltage and globvar_AFMdata.voltage != "": + text_string += "Ugap: " + globvar_AFMdata.voltage + ", " + if globvar_ThumbPara.feedback and globvar_AFMdata.feedback != "": + text_string += "FB: " + globvar_AFMdata.feedback + + # This loop is for building a block of the text introducing some "\n" + zaehler1 = 0 + zaehler2 = 0 + text_block = "" + + block_length = globvar_thumb_text_width + int(globvar_ThumbPara.text_block) + + while (zaehler1 < len(text_string)): + + if (text_string[zaehler1] == " "): + if (zaehler2 > block_length): + text_block = text_block + "\n" + zaehler2 = 0 + else: + text_block = text_block + text_string[zaehler1] + + else: + text_block = text_block + text_string[zaehler1] + + zaehler1 +=1 + zaehler2 +=1 + + return text_block + + +# The function, which creates the thumbnails for spectra +def create_thumb_spectra(x_data_list, + y_data_list, + image_nr, + image_name, + image_path, + channel_name): + + # Create figure + fig = plt.figure(figsize=(globvar_thumb_size_x, + globvar_thumb_size_y)) + + # Positioning of the graph inside the figure + plt.subplots_adjust(left=0.17, bottom=0.3, + right=0.95, top=0.95, + wspace=None, hspace=None) + + # Plot the whole stuff + for x_data, y_data in zip(x_data_list, y_data_list): + plt.plot(x_data, y_data) + + # Labels + plt.xlabel(globvar_AFMdata.spec_x_label[image_nr] + \ + " ("+globvar_AFMdata.spec_x_unit[image_nr]+")") + plt.ylabel(globvar_AFMdata.spec_y_label[image_nr] + \ + " ("+globvar_AFMdata.spec_y_unit[image_nr]+")") + + if channel_name in ID_abbreviations: + channel_name = ID_abbreviations[channel_name] + + # Some text ... + # 1. text below the spectra + fig.text(0.035 + float(globvar_ThumbPara.text_x), + 0.035 + float(globvar_ThumbPara.text_y), + spectra_text(image_name,image_nr), + fontname=globvar_ThumbPara.font, + size=int(globvar_ThumbPara.text_size)) + + # The channel, measurement number or whatever to the bottom right + fig.text(0.92, 0.32, + channel_name, + fontsize=13, + horizontalalignment="right") + # The x, y, z(z_offset) position to the bottom left + if globvar_AFMdata.spec_position != []: + fig.text(0.92, 0.36, + globvar_AFMdata.spec_position[image_nr], + fontsize=13, + horizontalalignment="right") + + # Save image now ! + plt.savefig(image_path, dpi=int(globvar_ThumbPara.res)) + plt.close(fig) + plt.clf() + # Create a white thumbnail image. This is needed as a space filler for + # the pdfs afterwards ... . The 'white' thumbnail is created only once. + # Name: 'dummy_image.png'. The path to the thumbnail: + image_dummy_path=os.path.join(globvar_AFMdir.thumbnail_directory, + "dummy_image") + # If it does not exist, create it. + if not os.path.isfile(image_dummy_path+".jpeg"): + fig=plt.figure(figsize=(globvar_thumb_size_x,globvar_thumb_size_y)) + plt.savefig(image_dummy_path, dpi=int(globvar_ThumbPara.res)) + plt.close(fig) + plt.clf() + + return True + + +# The text below a spectrum. The routine has been modified on 2022-01-29, +# for in particular the Nanonis spectroscopy. +def spectra_text(image_name, channel): + + # Cut the name if it has become too long! + if len(image_name) > 30: + image_name = image_name[:30] + "..." + + text_string = image_name + ", " + + if globvar_ThumbPara.date: + if globvar_AFMdata.date != "": + text_string += "--"+str(globvar_AFMdata.date)+"--, " + + if globvar_AFMdata.spec_points != []: + if globvar_AFMdata.spec_points[channel] != "": + text_string += "Points: "+str(globvar_AFMdata.spec_points[channel])+", " + + if globvar_AFMdata.spec_feedback != []: + if globvar_AFMdata.spec_feedback[channel] != "": + text_string += "Feedback: " + \ + str(globvar_AFMdata.spec_feedback[channel])+", " + + if globvar_AFMdata.spec_acquisition != []: + if globvar_AFMdata.spec_acquisition[channel] != "": + text_string += "Acq.time: "+str(float(globvar_AFMdata.spec_acquisition \ + [channel])*1000.0)+"ms, " + + if globvar_AFMdata.spec_delay != []: + if globvar_AFMdata.spec_delay[channel] != "": + text_string += "Delay: "+str(float(globvar_AFMdata.spec_delay \ + [channel])*1000.0)+"ms, " + + if globvar_AFMdata.spec_time != []: + if globvar_AFMdata.spec_time[channel] != "": + text_string += "Time: "+str(globvar_AFMdata.spec_time[channel]) + "ms, " + + if globvar_ThumbPara.gain: + if globvar_AFMdata.gain != "": + text_string += "Gain: "+str(globvar_AFMdata.gain)+", " + if globvar_ThumbPara.ampl: + if globvar_AFMdata.amplitude != "": + text_string += "Ampl: "+str(globvar_AFMdata.amplitude)+"nm, " + + # Other spectroscopy data that shall be displayed. + if globvar_AFMdata.spec_other != None: + text_string += globvar_AFMdata.spec_other + + # Change 2017-06-25 + # 1. Ugap and Feedback are listed at the end! + if globvar_ThumbPara.voltage: + if globvar_AFMdata.voltage != "": + text_string += "Ugap: "+str(globvar_AFMdata.voltage)+", " + if globvar_ThumbPara.feedback: + if globvar_AFMdata.feedback != "": + text_string += "FB: "+str(globvar_AFMdata.feedback) + + # This while loop is for building a block of the text introducing + # some "\n" + zaehler1 = 0 + zaehler2 = 0 + text_block = "" + + block_length = 50 + + while (zaehler1 < len(text_string)): + + if (text_string[zaehler1] == " "): + if (zaehler2 > block_length): + text_block = text_block + "\n" + zaehler2 = 0 + else: + text_block = text_block + text_string[zaehler1] + else: + text_block = text_block + text_string[zaehler1] + zaehler1 +=1 + zaehler2 +=1 + + # If some variables are simply not available, then it might be that there + # is a ',' at the end. Remove the ','. + if text_block[-1] == ',': + text_block = text_block[:-1] + if text_block[-2] == ',': + text_block = text_block[:-2] + + return text_block diff --git a/AFM_thumbs/Thumbs.pyc b/AFM_thumbs/Thumbs.pyc new file mode 100755 index 0000000000000000000000000000000000000000..bb42cbd331c6fb1d9c9d3ee927d32deb2f40a462 GIT binary patch literal 9510 zcmcIqTWlQXbv`q*Bt?q%+wvxwk}aFIB{^$SCfBxHlNRTpjS5g*qF-fleGg99FR)C_&IrCiM16= zeRrAxsT`EG!Hj!ID#NliqGXR$N2N9X~Z(hIV-VCWI49+KLk ztSy2bm9OFSo)UjdD@)>!Yvr)`6IwaK6TY=Pi6aj`#?SSn7u9N5Z?(@PeW+f#dh6!3 z3vVP2>KDr8Wn7CSc@)>edf-L3f^sdWCxL&lQEfyuuW1-Yz)-F>*6(^z;lh`N#S1TCmV)i z6dYGC6}mt)z#lx-I;x^s#FvCu}^RWxs5zk{Z>9 zw(j&uG9cTk?6aVggOUtNWr&)*nUm-(9X8BiU^3#M-N}e@n&~YvJ9(A3R1l-NJ&@ zEqQ&9d+{;uA9issD)%-_$5Y%Go^hcW`yjJT@qLXeUSc{BMt_LX61PL%aTpB+t?oJV6Y#<|j#- z+>?Y$+#Z(7bJ~Ivq=GL?wCJ$)dGV+8j$hz8aLdz59!tpwVp|k|9Ui9`9~V3${;c?O z;I?;0rH$Q;O67!9R&d{P>CFk*fnttH<)rxY6lrZ;b#7A$PKm#uZDLuZPj}J0i!&6k zgF`_5Gg_aJ_M&W$L+Z5bU{BD*pOWOWQu%2k_&w)#dtSCD%(PI_DXE+l|B&hZ3+FaP zz1SsI*SPbEVt>XA{P7dSp4%0h&)wd;aeq-A+M78Z(dWd6Ifo%%6#uaJN92KH@%Xyf zp&IaizrLUS>HX|`qMp&ApI6=Tk4m0`UQ#OWKP!1o@|;eR4q47j$jjVF-hV!$SCvlA z%eHE$|AN}N3%r2j3tGQOjt7oyagIx}13h?Jwx`*OIx6_9To(TrTm0jaUt;s_rca2! zLYDj|EYqAtaz!eyNabfGxhj>P)5SoM^SXd9O7u?8HuUSHqZmdS`{@Ga+axv%t^!wDR(Kb*ZJW zOb-?|(3Q|rRD)7d{>8~}zw%G_|8!Ly@OmRj8Z{V3IG3=zk(Ajt`R)H)RX?0Gn&oeP zgFpXe*zd(nuNdga4Xws>QzuTJI<<02TjBKJrITT_UJK(ccbyzSQ|7x}2ZXNZZY`{* z6|b!l;*BV*ZwxP0VVzUkJXsL;nH%#5ajvrAjXnYO(J1dZQjFTfM0}je>Z?YXBBli(}B!O~!>#=rwSh!aX^nBvhdJ=iX zL>X$hCLWp>mCa;aHI_@k#cJ48re-x!!BD_f6u7)HmxEL^#5Jo>JBDs)JuY~Dr4^e& zZ4J8+b%?y?Ra?R3C~8D1u48&MGOEQJje9z4(!mMvl8p4CSNFq6mk}qC%jd;qbYygn ztB3;xS_qzWbTbGx%`Vwm4Qtx!WoqeV`_;&7-HY`2aRwTAVn`QUna!QoNEp2>XOER? z6x7gtg;OZpQD$?)WKPwJXU9g=nj_E7Fv&kX8Q)}S@yIM$doWDVKb_hD->cf^{ur>&`; zL2ClvBo28 z8nh3gbq2DA>;Zeh8M2BzVwxh}%td_S(>Pg1%!n>_5a}vviq5G6M_2#|0myWY5sL4m zjd{S0{8=zF5CT6KzNTHdjNgzZIiS594j6$z6+;0W@~rltidnlP^-A=8sG$=A@fiMw@&l!Te`vp092)rFQ+|ZthW|a~2ebtL@RRs|p!@(*hW`i34>Sh; zktgwgto)-H|HsM?xCZ{wC-I-O*`>&dmwwXbeu0X#@d^7aDF1jSzo7iUFyJ5GFCQ%v z8QZUtjXV>?p%0*WSWK4=OiA>&DtIaz0TQt*MocjxOzR4Dr*>>r2*49trXNwJyhN76 zVSqR0#4Lw98dq5}`&Wn?nU(0Y@&gMQ{?p12xCSA!kMYk*v z=KWgE{Uz^*11HW4%( z&!LXSSwK2MlD-`C5y-?L2k>Ku*$eC$(v0M-sT`Wp5p1p_f3dFtq5uoeVl9xPwVZ7I z84y?x;_x|`j_VpC9$$hDfE{57bmD}@cPCC9U(%TP7JT5jB{l19ZMYe>tLK(9_PbFk zp{6eJ6e=|JuXte{Rhp-(UGP026>v66CAe$#XYB$At#!1Q+-KD>;RQGd%y zA&WDVXhw}D5>kk!*cFH6x>wb?lx}x)9a_JyY&@AltLZoH)in?(dd)ELs*G0Xr2#Sm z-#vkvPVC{ZG>Ty*Oj^F-^6F(o%iPi3Mm5Qtc?m;_BV68;`zB@3C2KgeUTvV`ILKuV zbF1vofE8gv0YPe5FT20VMsEJT7i?66=yW%6#{CAn8DFZf0)qPTr|;(7U%&(p@rj!# z1b%bI;_ry%SWAz7=SH;8a6D3?Z_b)=7Obg^$1xm}POpVud%~Ww>8}T@etXOrwg;?X zyGT{yq3z}}KZ^&eJC})=Dow;8kqEP;MgqPWP8lv1zBNt6!G-ST;*bbJ=B<5#N(o<2 zn_(lvvLJT=*84Qk2ua8Q;t#n-8yTM0bvmYJM}hMQh7C8-e^SOeZV8H3JX)N^W{aE zBQR{$eVSY}0e-7i>l92hO&g?Xf#sv9xo26t$U?0KZG(G`#d9bWUfc)VrZrYL&8MfW zh`|_U1*1rt6xs!CH5Sk`?1H?G>DuM(Jj&ZCkk{p7>AuE-=288C`vz-xVP@=-W@sW$ zp`m++T{MF3SJ=-pVSl07h(o^ka7*liDvG`IVj?u%?W<8M zSXSf818f%*2UU@5(j9j8Xm^t$Xl>nJq8#org}Ms$TqvHAZiMJWW_&_DF?h<{(Ekgn zqMGePRp}v~gvX7qp;Hb3@TAab!J_dz4D)#yFlZ=8z%!zNXOJe<>I38=Q0lb?V0eeD z0T|(a0IC_lBtottqZDcq73Cs6@dpmJuLuawAtFddOL#OD5G^52%kSu`5H>g<@KOQq zIT2lzsC}rw?9!B!XqpId@FGduAx%NWSq#}KDO5sxPiA^PP&SRXW>XO#s0d&iBf|8l z7)-2UKFGxMW@0{4F)-?QRgsGMNX5Wz8!@JDpO}v_F@2es%N7?6E$s<>R|UdR>4CO1K^*zuW6gxgC8-24;r779rUzK8;XI065Y^&Ky_x| z4IK!-V+QIwz`TJlxab=?5EJQ3FDgcz{G56ip|q_h54ocfy{~fNr;Ob9RW3ZBkvqD7 zLGNb^8k6Wl9SE3a27agm0cy;^F&(Ja@*xMo`w>l`M0}9rt4uheej zT>-?D0*I^59)NgJ0R-L#P=E^Cy3M9^L>GWCBG^Cxk>3RntN}p$w@m;6zc&j=p>Ix7 zXtI<>1L&OF?fhfyoRhuITg&r!Y_FR%IG$ZuSy@SOi2GGO(2wE}x{RC1ttBzyds@sZ zX_T6h7m8aeNmv6;p()1egSXEs45-Dx4>T2*f~wa^VZy7**bP=_NK!;WFI2Ck(C0~j zBIMf(_bn7%phEu0n6%vkCT(K-3Kfv+P#2c&w({{PkU}93%=EAtE2IX zTdgqlHS|~-jB5{a-ChUr4i-X>#O=Gk#wp%m@mu?N8wt|s>TccNX7BHy*bCv^+id$L zi{EAOdn_2IyWc{wjL)Z;f^+`}@>+BZ8k;-g$c7CdyEOuLFoHbTQ7s+oNcw$z-}h0& z33ma0X9QU_ttovdXJYc+?wH&jMr=Nu8-?q@$6kIKv*S_5^qp8ewIZf^tJdte+^YKw z8K`j0s+W}T9~uggg8JPsLJ&md!%G4ND%EgZ1rc3QU<*i)aoAor5{|nOjj3uZq_^9} zrFl}fgQ4zC6psqg^lEIf{&ci^DbAJGyeRb6t3hm(OCt?cIO@E', enter) + widget.bind('', leave) + widget.bind('', leave) diff --git a/AFM_thumbs/ToolTip.pyc b/AFM_thumbs/ToolTip.pyc new file mode 100755 index 0000000000000000000000000000000000000000..4fd85151a4974607512bf9bc53455dfd96429953 GIT binary patch literal 2652 zcmcImZEqVz5S~51BzByaz9mRSl_3f;h2j?R0a;O?At|bqx{_^CsE|%)?>au`d}rOR z<5-G61yT3~{1bi;pZUrUfM@31ChBK%@y^Zc&Cbrw%d^S-vtIu5?>~O%(c;PB{Vj%l z1fua%6cKf_M@CU!kV)HW zd+?V-47&?rU;t)GEWxCDYtj=YPpx*1o$7fYJXrV+!`4AA6D@u1ckul(N0$ZKS*$Hwf65VpmrcW%L|V}tQ$-rCaAjatv9QY3 z!Paxs_h_4^XS%y9%9^DgBF-Qn8{R-8$>(^5R^2 zjob$53h8yy8{{@g*K)~xwx{v4AAxN&+*zYBiS1-OPEu!dqwyl>y^`W- zyIEvhfmaE~B{ne8*sXzylczlwo(IlYDJFJ8+GRMgF6_@-8A{!tcXpa4lUQ5sq}@Iq z^H>~9O%$5GnCd2}HYw`Z4a8JGiJj=UV33RgDci4QB2Lm#5Q$6SIM5f;TCKY<-MYtw zLsPrO+y)bNSPERscDu=i?1%XD6F*H7_r9DJZYLQ>=G;W?4%SacesXToG=z(2i`4X7 zW@O}_nq*{LI+G@IXR=8zh$4~wsWd^S7agZ5BFkYs3A(V#UY#62>&R65<;n9SnHnQj zHSUU*5IF!RtHqHMlf8@Vwb*bf1|qgugUWInm^ZZp07y7y9d%!A zt986{UIjh90Y0xjP`APNxXc(;cu04D3MT92xj-d&Kpy%%-D8TbM#rjHP_QlN+sqOx z`O9Io6qZJ%rAdZgS&Z1T|L5ofq#H;71{>UfuA-`O8W-pm2P5PAQs=%uO7tXx*kbr? zJ!JAZ$hCLEEeT#*9O5d5baT-w6-zq;svIzm7Y`eNIEg$!>vu(Oh~D55luPPYV)SGY z8S#ikAf*5=kP~os^L@`H zudLhRD?B^RW9BfH>S$zwbMu^yW{wJm?jN)J2N{3D8V8o4cK>kVToONea*&0Q9n4@4 zSYG485G2fi@d=Axf{4%8ac}WCmKEzw*y^PQH-yir^wCepY`y|Qs-kXto8Fe%QcdwL s`&a8MLv*ivf66Jt#zI-`gXJ_WM zdGqGYtK0qavolvt{i0B!__rDFoA3m$SxCf07N9|vLEJ^$P1P>4fb@{nO}v1t9^ziI z77#BatCx5YISXjDwUC^J#EWUQ(*tS|aYp%kR>a{Yw3^Sxa}J)Rc$VQg7teA$=OIov zQY|K4K~68Ih2X|{@k-F(@v8W}8t*Q;BSXA~ju{9zKV@8?4C^f73&~nSd=Xh^6JJc$ zImDNcwUqc$vX&9D)ErHec`or~#A|^qC%&Al^N6n?YX$K-vQ`pbN!BXj^<=Fk&XTo; zxR0#!iLWB-0^+NQuOaRy&Jk}Q-blQOcz}2_@wLQ{Aij?Hdg2?1A4$B0D$B^akoZx= zH&O*!y@>d?h#yTnNPH9V5LKYwi;1@q4-=0Nj}mVq-cG!Oc#JBG$hw61X5yX1yNGua z?;##1o*=$OLoX%HlVuW5l7(7Lk+qiiRaM#J7>Pj(8tgR}$|hYdx_=R+jhx zS$)K}lXVsGL9$S<$B>1p*<_)1k0lEgERcmd7Rf?2OJt#@OcpBZkcIk|$wHMYWTDp6 zWTE0NS*ZIRWTEU1aSfXNa7wFC=&oU1y=8UQ8C+>LtW4CBBdNWyCKh zeg*L>iC;zhYU0-rzn1uQ#IGlQ1MwS)-$eXo;o7`!x1ev2kwX7ITNFE{wS zH2DgHR~o#^;MHmJH3pw=@C8O0@=DQpO?#oi7a4r9!Iz|IFE!XS_%egnrfDxX_zHv9 z8GNO(B>AK!UvF^M;68(|N|Rr0@HGba8=Om%Z!mbH!J7;oNRv+yf0Fo9gnw&iG z{p3uMa|=0>#GfJlEb-@vKTrGx;x7_^iTKOJUm^Y~@z;pIPW%nxZxVlt_}j$aA^tA$ z_lUnw`~%`Y*QU9Z_=j{ik+YYaadK{@V_h@?_hsEi{1?POBK|S)PpASnyN~!Use+*W z#6Km+qOw8!SCaS`(SGXy@n0w0pQYT}iT@_y{%y)VNc?vR_kooA7~;QAxc`uHZQ`FN z+<#2Dk0t&^!u_X|TObFSpzTime=I{*i5y69>NvkfP=zS^N7@vBxCqi78z76xf!aF6 zI|l7LI2%E^4Q=iQ_gDDs2@Zgtcij4P!Dn;4TJ+u0 zw3!W^Aav`MzRd1I7*4x|z?^bwHK*PYGE{YD3w3sU^RPKtny$GV24$zp9Z_<*T#!Nj z0~-eh`ZsRsA9!TYBV_K{0Yyywf+gTUEHe_;JRB?l!!-L5vnaQzp*r|FANEPOM&kOrEftASw=OV_i=lSf`3!%eiv9$%6@B$x8Doug`(ed zN{1kZWU~Ts&={fb7Mmfe5SV4(t8K|>O%RR-qfD?AP->G(fRKgYO?g~sZHaWSj{Dcu z`q%AOg}G^?Rn0Xl^IR@@XLYi@G0po5hF z)3=mff?h|UeiyBnp^ITT(#8|~# zXDrpk>rh0-C-NQkX-h@s(~nw1DC(LzBaN`xR-^C>Fa8ZbhotB6@ldNs$) z@7QUU-72i1#bEcqo59_9Wz(${Dk#FOn+23pZPw~$CNnkd2Bz1L?98eY24>4^nnA-U zxn;LxPJ1(E2A#K+B%UrDcFfQd3Fqb$JoZ#&`I5(fx11=GU@r<$?@$OrxJ>l6!1QZ@ zdALw*I(-jWOgQbB8T7Bvm-JAHFe0@CMPxlD8Zvz+fOb?PHXOeMr+J!% zbmTF&m>p>`cQy-EH*B4r&`IREnca-cwxK#^;2uHE9zw}l`*Iq+Gb=N6X2W0#+3`NJ z;RUYN{1R?!3JeG*$t7oICL^|2uePN3HFdc0Di}=ByJuV|LE3jMJfRshi~W(4@O;+^*2ew& zVbn)`(MbgfWNaI&m#R&MlfqO%27Dd&(Ejyyhl(ufnvTe7qli*3)Zz2cJ||1inR}9; z;m$hMlSR&T)H{`Lg~(?8+SE$TudJzK(L|e*3p+AR2H*PYruD)2~HBPql##oN>x2I zI~CtKX|_*YE4luxYc-2@_hKS z85b#a2$Ni8G>h^x8!R3dB{(3Z@%mk#`>k^m^d_N`J<*wrY}%^qh2v%e=XB0^bj%pcp8v|#9B^`HClz3cQl-e%zltZ zPUj+K;t5q)%qmXSW8!%i@{D7tHMo%vW%S^vCTTr$fe*pWNw_mi(=gg$)`wm!Uq~>Do1`j9;P_0jA(zrU&03D<`gm5Pjul2zHO zR=pWXREFn3mk73)8JSAUuiqSox|+T;qPf$l9!6`&x`(fk(E$Qf`~qB5lt7YWIQkx9`qVn4~ZJn+163l>FXOjIyF9#9p9cGn%I%ue{^hASO=^l z2ZO66#Zcj3;+u~S?Vi{*Hg)UB=+T%xczbS8xq|4v!-1WL4m#B=L`5z;M|WlSj_v6i z4EiLiQRkrVXFVSwqxpPxJTC?9svg{QVBhRPiHx{5LUe(9V1y4I*j7HM3ur;yDjcZ8 zN4Jgbni|cIjs(|Bo`{uogTQSRWQK6$0mlR#>V#?l~9Z=?>Uj`j`eI?B@J`;^y+nx_@Y3Yg0_Tt#peP`p(GXx>mZCx()C z(bOZM#2IPpLf3dZC$ItJ_`dG1#3nTA`&bqBAT|buO}ZckVs1)U11W1Dlr{2@jbTD% z8%@=v0TUQ*98D#~sJKxPq3qH?N~yreHhW}jyDmaeO7z}06_vGbDlT;2)PO5{7s}r5 zJ1vcucUT#C4=Az~iy|#qkVrU0#v(>mu-Lwe2q|^HBmFAM&a1LYGVY6S)MfKT({EsP zs%n(H+PNqOmeyB-qNqwns4%s_i6-(88Kp7sj$;ZH6(wP^vC~c$l_QJz?RBK~Ld__~ zqY90eoI+iN%wxt?L?vWvY&%9h+m9KtQLtljugatW0qml#D!UmDQ-hJU=mEp(G*D^m ztr!DUR82AscN1^_V9)eoiy!s9@vjV4HtX+)gE8kvgK?Y(1~pqBH4>AksMaOdBD7H{ z>+i>dm6zQozn>=gd}*-qnfvAUv%$*aj^2si4+bmWe(Q(uL!6)04&wKn!ODUU$`557 zxqj7(UgztBmAlN=PbTgG=TZ5)ezJPqcL!A=&|WLBeXSUDE2yYa8bok00#&dO?N&&r zs1<|~#cXYEugB>2`qpO3ok-A$X3Cvt<~fd#M=QtZxUXC(RpM%PB2J~FWn(;QSubtb zq#>ncE62C&bZ}T(Rs-5Cdq>=|(wtI(Lb;Z-Y%ytBO(HE@l074_18JgRJi1ls5*;Nv zxRP$~qPq;btBa1}-=KTD=+0hj9wQz_K$2=F&TUlNsTZ)ok%renxE)caW*ce_yM+xw z+1}MGHtS*24zOZ%c*6+ha~q0oy>q|0y*s&KZ^3tE>K)`7E!`l#k=;^Q@@kDoKTWo= z#fdB?ZQ@~!f-c5Pad9zj?r~;Rq#@)|)yCfjtDG#A*7`^FBAxpAsOa-xCL?fhg`f=hh>@`zxn)GFA}ACzhX zfi8i7>{bM1k0Kx!C<3xq5s(WN0l7#Kkc$-onNbAfS&D#Mq6o;d6#;pUA|RJ40&xfIMFjkQXQd@Mx}`(!C! zucc^XR?%q9t`-|F#nmp8b+%?9>u9xG%$?)$O%}h}^#E>=D4vz{wbr=&gY$i9<$ zHRVeAk=R%UY1zt-#89-Qh3I-&D~!DSf*ma`G#@Z<3W7L0!Bra4J*jh7a=r#CUl-sBXb8AdfGjZbfq+mzQ@~*XGXiD>v;-Ux@HheJtCYV> zz~coxLBJCQJW0Tl1soFq7eM)^2)IYUQw2Otz|#dhL%=fyJWIf{1w2QR4;Y0yLz}gA2Uh(|E5=3Zvo;*Ky3Lkg>L}Eqw2Q=?s#&H^Ud1Dl)L_-&0GLwt~WwnNVCaGt{xJBLPp7A}S%7n>@cUL@i=o$fs z*OBi&V&h26$2PM1{3AB@YTTl)i)5AIh#egw#Y8;jiT;k*7&}#ezzVY(0XrIY*>~<# ziIH`>W>o=EJsEOjS|?jc_N=X9Xl)|8S|~czc7)b(5n6T>K?Zrvp_NFN=GpKdRG^j7 z80ly%EvuZ4eQR}R%4DZnXlc7BDMxedJdzWoc68BcG_GlM51TuFX){WYCv`Jo4hkW{!Z-%<=Rlj7R%)=7{;@Rf>STS`m=fC<3xy5s*1WKyFY35;0*$F%JD|Q+VhS#3HfFLZxQfT0dEta z6B600&c9uN&O6>A*gFNhOTfDYyhp%$1-wtd`vrVJzy}5Vwt(Le@Vf#&BH%*;eow$h z1^m8%j|un#0e>jqj|BX&fIkuNrvg4M;1dG=Ou#1vdx&3{I~X9avtz~=>gLBJOU zd`ZBU1$;%oR{^pjY~&Lkep)0w6TT!5<>}c2EjZCHWPi~B!W+%p) znq7yLNUl25P0Gzmvd93w4lIl3OtdM!a*5W#Waw_M$kB~Qg*^`lCK^3=V2Nqa^<6gJ zV%Q?u9#^93j%Hp36jJ3q1ET8gS%G=FEp7HV!x5Xwe?vsV(*fphIQ<&(#n(!tS1o&u z#oeJ;Kx#12o)|X5Y^+moln|yCBkJ0UNBd4>F;F`+c{grft49^xJxp5>mzWmWVJzPQ zzpaA#tG(zKUuh-Aa=iMr_0MR({U!uBln8*{Dm^JxKCXf|XI9^0Zc<8zs=ou)nNoEl zsVN!9sajXY+i*F=IkSH9+o+wFNYQJ!AW64#DuT)HL?jA7@fa{U59|!@I24RCdSI|K z{|DNKh9?a_jq)QgJ0hO6{1d{XWd8@sPY+ZRo-8tqf<TD-u+v8zv2|-pK$FWy?-%3^-s$`0g3WY%Rd2`=kgz_{-+3!*d1=SJ-%V4 zP2qBYO4TbKF8Ek|$Om}3)xP?q?C5kzXD70^ymD@&_V;3XdYk0ha`2&=EVL5_w(9i^ zSJvnWFKFPVY%nLC9_F6g5eFZ<*`XWaAV5}ANy@s1^X)}o;EHZpx4b*ck}J6$QmpAn z(P)L!m^nuiS~>e#)e#tfbQbF(T+tDvCt`XegY(~01hnRq6s6F!ZT-MuZYroS`ee=C zbgF=X@KOjcIWamsY45?E{kj|2(RE6@*2MKHy;>ZuJ0Xs2=!d=+l)Of(Gp49vyyljC z)PHh#XxC6@pfu;)KwRR~udPHub3^0~z6M>0Adw7TO4%c~?iwE3Gdd?zDe;8xBwtws zpAeX4EjD;UXwWQ|-C5n=k(G0Y7Q~W;h5PDp+hTnbsF4agF0&n^%`PEHfgM4j3eDaL z0vs!Kgove0P1$uANOXfo349u*=VKu7DO8HWq8CQ-<=deI*YiDDQXw|uV9$##^$CTe zJx~kcuo>O>0$;kM+-Q_#2*~K-g9xQtVQ~cQFL7~t=|eV25GKXhxcJdY#+N@3D#wR% z)(BMYf5hqKz$wAyQwr^1l9yfpiR0s7Ea69YHl*VrQe^e<#TDt~DKEOZBE1)^^ma#5 zkX(;XrEC^ay;PHOnMF3KA`#@4MJlRZf|0gI*zxyZ;>N-?%hI$eZ*0WI$C=4xRS^W7 z_5q(X3K)m<-g1&4qU1)ZHVne!%dCn?+o&}P)p3(mnhGqZef?BatDJC?);PikRE5B! zL(w==6*uhk7#9JBV$pXFyLy@#%yksuA$!=X6}_T2dz>@IB{DnuqA)Tpy;f$+?M|t5 zM8y|Q#V#U-UK4GT+vOIjv|o}qzO34gp<>Do&Jnk9+(;q<$lW;AV&bdia#Nre5E4$Y z!04I66{GTscffDyor(N?p!2fToWEayY>4D#S)P}*Vst(%cL+NNkzHfB<-C2)ScAKJ za$#XkG~u~^{=1S-=lC)uH-jc{&ra_@NcW$Jzrw@)J=vC16BNF+&{&w+U@TmGgRu;>@bK3SuF-8Q>;W!M z0*&SP>ou12EHPFZOMovnR(AI;LY(MtL5lVCb_4G|;ZI^L09T%N8Y$uUzpkamQe$z~ z8si+4wbEF#u(wOflXy!YTQ?vi=1 r=2eSV-L-1Xs)eh1R`sm!zRb7;n!3#B?^=m;%cWMR&r-pzKJpO^ngtC`=;JdY0yWG-FVdFtywu&lpXkr#*l0l56AO(GBP{bI8ig!io2B8K37K(M3M#MU-^3Tt|Tg_}>;8}sMNvNTg&UYb8rmSr$* z>KLCs{4-Gw(A4*%sZzb>2hbhtcq@&1LzYCXg4SHe>Nm?3*RL=f0bU8XY`C6*%fANJ zz*=Mh7i`RGSub!|2oj6-Vp8xI7_-)xx2F9G?LVpSZGAtj`*id# zwBOPGN$pQ-{~Ow$(f&d0@7MlN-)HsxpLF~{&*(Y2yQyP0>DW6uHc#H`+PhhK*O(mD z{z3A;ru|!t{|W6MBL9l^Z#DiC+CNPG6JlhQtvni}7W<~GpBGnoi;K}Se2w`6Gg};= zHjFC7*eY9NXT@<#<%1obWD9KmZv!Vti)|zD%Z!j!j2yMZ7)+S$(-MEsFf-F=HcrcO zvwFUbziK-P&4vDjT0L;3D+*#E*dCB#|WK-6>K;rk9NQ5>T!z3w(Hb(x&l11>{J-Bzt6}9qSf1&i#<@seVST6b1 zGCY~RQ?QQq&ey!Xu%=1@E;c{f)t`7z^L&_-F6x)`C-^Gp`Ujw~c%J3)VmVIlk$bR! zbue<-EXy)1$1*(2Q;=hGxf?Vp`0en84*-8WT9>~EE6oyX4A69j%cojQaCqMx@Wq6H zwJ3KB`zXv3kp%00vZlbgAFXTLyI`{W!2hzjbIx%8qSk6s7OXtkjA&gXYX+V{|T&&M@g*iqRSA(a9Pe zTH*3vM&~B!jFHaG7@cih9q$iDWjlT=`Gi*Ca-3AgDRw+YWk*Ei`IQTS4e`KZ;7)yx zukzJIDmBandb5WQkoP@O;7hO3!#xk%)qhn8JuPes=1( zB_07jS-_{_v?Mb0Ei~kFWhsbOGodqIuAHI!ewgYKSuyK$U?n%9EssqO8$^yo*2pY2 z1K12Dlr7qQJ1ZH zT<(Lh;<@ws!*b_DXJ!fHPD{-!IZw03fwey0olSB@%_Xp|s2SvKGuau){+-T#lj2|p zAm5B+zeiT&&wG^3yuX<20hsHSysPs+rN|saej3UDoUF*7&vpK*UW&dWxpPSMC9ChOhLVsv0HfqkvhrOGhrd}ws8kq$D5 z$!jq>qg|Z{RmMPt%VDE(msF5IOx}%A*&b2(BC3p|reBPqN>Pu)U$Ty8)Qho~! zk79%Dkl)5;4>U3CaOySBEiKdn`5lZ}&kgw)S|_o29Ge(i$nS#VmvH$4nqEqD$k3%l z-Y}%Y0Hnp2Bm|BaPl(qZmJr9xDtiz@jGF8RAq1TsTDWfjLdZL6hRRQ9_8}iW>CQ^| z8Cj7JpV3TY-g-V9Fe^#TU&RNSx8Q+&8LYO;q@wt6S?jFl!%Id-trW$F-W8&B6dyV| z>-q43(Rr6fReX52`<=|^QG6hs4SX0fDtAal@!?L4isFM(xi=pQF?=ZKak#9~IK6zR z_Ka7EM0EI2pr^^t7XHuqkZ#t?4-1Iz!E*gGT=xZtC@R)tp^J+Du!X=8;{ow800Mqm zIJ7i#>L>OmTTn|GwuB9ft|-_l^YX@$kduP1GPA7lIMY=5@)-T>P-u|HM2ZeOcmz`a zM4_Mn|3bkEhn-U<8;&>fs?JtR29HXYBiV10CLVg;*4agqjY#>2&i;tvaMSToB>NUw zano^&vYGdHlZ~4WCikg)=nYdWUl2 zOGjrtTy7YhE2N{~awSGb!KI_q3l}akMn@go6kKk{=qR|5&IY&~(JHV9rB9=dKl@@- z6kL?bz2Pz!1D827&RaB2qG$8*R?m2Ik%$gl<}d<|G;_Uhp?wGKIOyDfRTVns%tUq| z_j!K#?`%F&HSe4&A7bnAefWxF@I8GGI#}??vJ_l)&rv0A6Y|Amxo^hc*rsfW&l*jhuCHtzTkH04W0FpnzNCt*U17$ zEXZQs2PP{GSs&}H_bCQSJ7z3JBA^^)QOT3GM_D2d@*9g!>Zk-oolYKbOHml;MwwI; zrp!&0`D2v{^qQnGp`5cJ7l=l=UH)P*hshUBu1C30%-N6&6gz5px6HRx<(v0S=C3Ie z$~PM_fm@Jy)nuxI4Q>S$ZU0J{P_WsM39N$5V8x4+S5BGo3YBbpJBCHJ*50Q(6+!Mo}|5^Ody7C|RNxI)4a8Wqt&wIS!prG{9pyH8>H$;acR V!?S=~`m>!$=b&={{ti3oe*;#Ap0@x1 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Channel.cpython-38.pyc b/AFM_thumbs/__pycache__/Channel.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b78e13b5ccc36a4c6d4b7d4ba17e8dadbeab6d0c GIT binary patch literal 6701 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Command_line.cpython-36.pyc b/AFM_thumbs/__pycache__/Command_line.cpython-36.pyc new file mode 100755 index 0000000000000000000000000000000000000000..c39e501c5f1513536958d59437267ed4b01a41a8 GIT binary patch literal 5911 zcmdT|O>7&-72ZFR%N0dYKbC*uIBQ#u#l(^lCvjRgjqO@d?EKiOtk@~rlwER`;!-4+ znqAq_LP85D1$?LhAA+2Vp3+;6J@nW^PC-vaFvqrs_*Mit1qIsg&8}7}8HEd@my+1o zH}9MI=I_nUd-KZhur(i@_(kWOqWn$C{4~gy@dTeEVG2{bN-ch?H5GZStM&Anu98mg z8ogXCCuIY2zLuAA4sxMZka8ZfSu>?vfLyEvoFyvNum8^e2?skfBs_#^aMxlvU`>E z1CNR4DxQF;iV|X}c2rdfRi-hW84t8=WlQO3EXVS!z)V(T78`ni1(MnlrjfK|Oyi!m zg2^nfF*eR79$;BfQr}U2rfsX++Lqcen6g^re+_e;e5XM99W}U*b`QyRO?E=Qi$JU$ zbz2XIwsg`UUy?QdlGZHksQizl4~OgJ{xNVoN4diaJ9=12*lc>UW6&F0dP~1WJk$g2 zp~@$ybVjyPSzAd;u#>WeY#BAqqmAPU^C^1wXTd@Bia-}L=xK>opm{baKSgh*z`V}f zh&0QJCf5UJ#l2{s8E}8a{;4l5E%+!Z#)_9`FH|*=lZ8a#uFC@$Vx-NmXlP~z7UMQU zpKpp>fR`)sLCC%SiYTT?v>vuy`<~BNp|?}@IlIOEo_(+FHQTn+?b<$yaXVOVq@A-a<54*BkUe~q#mJJ)OORKHURt=GNnzU(z5pE7# zVK6rch0%7q1N6Qbm1bt*+EiIsdvbJ}IxHy%PS_@1Qe>K%wP)<*winp(T-kmfT|;Am z?Zsth*e--Z&9?6cZhsc74x-%5%z(9ojwIS5+H4b<$?^Kh)KHnl`32dZzz*6pRSnmc zv(0R;ANo(%o2t&ou-o_qC5MnicRq;iAf3cucCfi;506Zm0*3Iv&0ggVuweI<#xC?vxb2DKrE;)-?J zIlouhG;L*0GK2Fkx)pxp^ma<{DmqZqKT+;#I%bbNZ~_#bE(6 z6s2ZH@gk^$+ej46)JmGEYVvOy2PHFK(k;ELnwqIwDm`V@(lxCDO-V1Q^tV(4lBrp7 zYM2^-0nAOZTKdu1L{lKoCZ4CWX^T!LoFf~@x72y%qls;eX!P2s&#EqS*zSp zHYO!n25Lxj7W&yc%0qqQOF|y%AN>hfPGTP}Dl9K09_m{f&aJs$Ye#Wd1guEce2LIq(}Jz88_Vr9}kRQNxo z{R(Uv!)!Fsx5M&|vK^1?dxUQ3;8*$2W%=(X&Ce=~z0Vn-5uI>j$#@JV(w!LOzGGO!_&XW=B%4a`-%1;LmoV7HDRw5&$M*kTqCd@^ zPxOD5<=;>AQ|xS_|3})+jZ8ad*fimMZxlCE^!fVPwQG0Cmz##4Ikuyz$_9Kqd=tj7 zv#XNV;8TmrLt||UUxafKo7&y=4-I}fG&x-Qi(((Lwx5woBf&J4bvVSGnzuL$CV#59{*w1CymkzLh`vmqJzX0~!+J$}W z_;R4{Ilct;nGE}_eeAilr6;m~BH2IL$3By=e-8H94Eyo{_RpWl{*7e+2JA1%d7s9- z&r0?@FN1v!>@Ugn{9uTh9&Qk4L4eZKvONyL~8ZVJ!Lgf=5SjWbq?NMB%F6UGMb+ zp)d7kK;0K7|0FV6SfTFleIE96g zHNPR>YWz)A60G*+|`gfUHfJndqky0 z*Ii9>qet*ZJ-yatBLSK6mG3I;3)-Bd4WO_k@ny0Z2WV zEbLSm9T=#{lUdfWzVf{(it4Q&j5m9o3Izyq z2bfESX`$PiK$zq)!v_yV5k{DZc~9Dr$jfV&fR~8WT5)}RK=@{TgVW`U$hEq@6K3?A zyeRd}E&^CM{v*^k3IdWC0ezA2w{-dI17T3xqDa#Y#~n8T6a&Obm84TheuXFa4vA8* z$R}6xYCeAJW%A_lj6q8e{PxTveRuNT<&#H=ieVu)`9FAeS?N8AR*xYTAZ}Bp`*WxE zVgG&Z1V$!Dq{(?`(iG5-%${Nl8DHFmu%c`u#^|UW4IZQa%Te#6um9--{sZNAL@JS}Ob6ZKYfx9qkD<|;} zapKW!kVf~6xfWSfwInQja0gvK?0OARk_(D(3|~`@>%nA$?XEptISL)C%}=2B{5d4T zY&f{`02R+s7GLmwxX7{Vc}SmClQ<;Is0t0gn&)eH)y8qb5%1snJr9;f=2k1FO3sN- z4|@at4plv1Vb`IX!Wk6M$){+BhUgA!IDzk!&2)$|!nb zFD9M6?QqX&blrF-%C5>W$`A2hly)II pml>8EAnhJuzR~m9de?pP8RP;RiHYHqv^b32m+IyR<}Z~q{|0R(M&bYf literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Command_line.cpython-38.pyc b/AFM_thumbs/__pycache__/Command_line.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..845f3f2279e4b143af45af2234466f1745192a56 GIT binary patch literal 5668 zcmb_gOKcm*8QvGk<%*)7mY+%1j$d>vDREl2FpTD5SE<{^5o{$**#_*AGn7_Z?ozWW zTUt#Zny>?wyFdJcM+Ls7V=6g~9RL(w?>{^5!uEygH}lGxpU z{%_`+$3Kt%pLa(`9Sy(h>GMBZy{Kt_qeTDDK;m^g@$c|r8q))<+WqQP9cd#lT4vSM zNoNLDD_6}a*@B#}=9Qd-T&Nb5oQG^zZ6y~V7pp}j+mM~AqvRswk?M$&9mu6>Ny#I@ zXscW;E4dVmwZ^OCkVjehBdt2Y#@IN%lWc-b;ycCk+gfGn3$$9hS-fCQP}jC0hJhU`XSU&5QzqL zZ|`S8u<=~O6Ej`Y5}50ru4{?T3}!Oxfw8T1v{i%USe_M_&5F!nBM)FCr7dA7Nn6HH z?rX;}panL`rr7iYn6{(sn7i6fjct9~=;*5!)7FaOQIcED?-VG#tH<|I?;%yM&1TfM z2*kOkZ=1zKR?qj#h$yF8jh3B zY{cF&zv7;0i)h*XNu*|5{6SjmDqfkpTrp%$Ws-$ET*R1+sWHpak=a?y8s11Eu_bdc zK3wMGMEK#dEcTFeBU$0@-AJrK@AlLe-KL0I?%fr?vEq6`;6}(M+<2qjBlUUgdV;(B z4iA$JX>NA5&6?80EA0?%e-(X$SMP@cu>3#vV_8?Vq%)w!!io4J0N zM9>`OF6thqmL+;i#VxhJY{PcBr9lDpuX$oQ783xa5yjG?i6C=+j7cCZj9el{$TTyQVN7uB<@-}q z944qhkd4u)QCXVside`()(UA+9de{wutrn*x0*PEV*l>Uw>a~?`9{F!uX_m(>Fv$G z@6OJ;mtMYfX?_u#f$&-_EZX_Stz;z%Yy0+}?-$pS4ITu%mTe8Sw#xl#f1YbmtL25P z7GV3wq>`mZpW-F7CtkrzGi;+|*t*gE|0iz`k-y9rOQvI%b=$B_N2jN(JEmn=j}60k zoHxN?mUR0o%dj6?X8uddvM6mh-M3{M;vDK~;FRh82F{;bc{+bObOPb5=;+tA4`#Lv zW^|0TyeKm>(QAgTt)E>lD{LH?rLYUoUR}RH+K1)`pFy8f`Xya^XstUeuTo)Rb__bL zerX)V>5y2p94jj1{sAP<9EJR5zXb9Z*oe~pVL)rMlG6TZKwD&^O8eIVt;5Pn`>z4* z2pc0UP7t7bEku1KHlFFv4(LbOM5eDN<$Kz8U%xu0;(31{|5)gBOg4E`1Lqi<%F2G2 zj1Tr(jmZR?&hSr$;*;!9hJQK~pJFo^{%9yZjWe41Y6xQ}euy2(@KZza8Jy+a@^22s z53^$#ULT4dVaGH4!=d<5b|S++8Hyic&t>?hL-FJ6`3!$F6hFaUP`LRu{eO+35`b^}rlD#m;2<-w)_tWSE<#uk8o%8S^CwH;tdwW4eaa!V-TG^Mdx{oRB^xm3(Xo<^- zwOZM^u;0pEc#p_=`KgS7%JUKO1&Z+^7{P&_S>iqzU)s5Fu%#LE{iia2rkMW%=FfV} zFJ;V+zcLr?0xCfc8l z-){4@M0kPwPB(r?ON*SZ^-|@9NVL3UFD)%{I#TC0S^y{34O{zidsF7$X*Oe?$ijP3 zkf5v5Uf`V7y~dif-tzoV=1?7HviL@;jUI0>E^}{$%K=X(zPpK5^xQ>+5VCN4qYkGk zPRk1vCZL}jK?Fu+{B18r+k2U}Pz`dB1=7+j-VPAblJgm-QwX_TR7oLsuM754gx2}( zIL)h|+D+{r!oOMY6BlL3 z(nN?1sRet($kJMcb!DDxTEpO|@0Kj8FWFE!N~{MF2B^5qlWy2AExHnrRvqn>qg^xB zx@MH6EUBy~3%E`o>%j|!(GZ;=g0mPbgm@18VXONk%S4%F?(A8n*|W^DvJ9wT8OwuZ zWX>a_$PyYZyjnNBL1kTg$YReFve;6lAm7&}H_Q|pV+Ex3c7uexn>Y~ zNuPd86qUXaAcBK~Jw|OKXFK!7(H0eeD%ZN!mKN15i!|);brA}auibr}CFupcet{=` zjF(n$Ok210ybh<8zNQ1`H;-o$DSF`KKJh4LmmFS{n$*WF2hz;{;UUJoX9l$%A!ivn zIM{dwQ|;$wY*~Fn>kBU(IQOOJHbae_5es}%W?)sQ%G~KGjo>D}_ zXC|$-c#DcYF~b(1JBTY4Qc+^S}bR#Pd^_9NSyA4#~teot_vJ+1&MirB( pIiVWY*DcjST0PRf+KSjlz`sMo9J_dRyHnB+{7w5^`{&x3{{j&zB5?o! literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Initialize.cpython-36.pyc b/AFM_thumbs/__pycache__/Initialize.cpython-36.pyc new file mode 100755 index 0000000000000000000000000000000000000000..a34fd5fc02a791a415a929951307b63224d48c0c GIT binary patch literal 3960 zcmbVPTaVku6(%W4qNvNtyS8_|PFrr;W~0>JP2(0Qf;6a`+G#G{q-&!ESQG>$j#k{I zNM?reN`m%j+xI;5p^tsdpD6k}21OCHdGTM!OZ&|sbz$PZRD#Z&o6ejW&iUr>LAz~# z@kXcr_N$uqZ*Ajafd2)4;;$fq7U+@Y=A-WFkd4R~SKNxObQSQXYZ7mQuew#@tKe&H zjrbb)x?3l{4&HJt;w|tEw?TXZyzSb=+u)mS6MQph{ZVsUK|APRYzJFG7h@;55o}}J z3iPL1Z|4QF)J}T3+&YVr{&Syu4G&h!-XQRou|EbSQZX)#uOu%h- z={88>VR$wSBj%-kHiBvU+a_rDmfCcdjgr_4Le2(R!e_AEUfKdS^e0i~_+9KK}+98T# zfS6sPH;8T%-649D=q;kRiS82JBYKDE{+X6(=XY_OwLcl}Xe7N-lD@N)0t0h>mps0= z)RE+rq=S<5YDxNjN%}!a`e8|Wtt1_mq}NMQuOz)ul73W@?v* z5*^0MiNvNApWa(sod;>61evT&J%M8+YqNZ;PrWppvPjlv1yh}R$#5vEGaBm8lPL4g znCy<3FD9IgS)6&{4kacMZJ_KskDd<<4o3xo6cmD7!jVuek5xo z%w<)ih#@V`gg4~uGuiORX%uFYfXS*KpG8bI#lVlfNg5=Vv9!b`W2rZM6KdkpkuR8R z<-$XcP1!)!bLltIJo)70k*s6g3NB=QF!JLVOEo8`AK93D{&U9F+N`-Z^c6TL4vQBo zlkK@TK*jaBub@CS;k{06?v1hFDh7Xw`H&&t1v#Z`;7vUW-ztR2?_y63NN(@VvR;Q*H%Yk zX9G|a04cD(4}<8dGo;u4k8ej;-x|@J|KF59#4IbIvLLL0>Pr9>pgttzs+d_IOmvV;#vXI7Wi&pBhRnM;|6Bk!aQH8 z@k-CO&vzEcThHU&%yYdmvRez|T3;CFxACvtYkd!Q{Dt|s&i5$FO=Z2RAoiY$4gKHq z`4^R-i4~doTnqDB|6CUzLb{{)Vip@-EqGN6uPS+^}W)7Q%B6AMVrqGQU`(Y%Wx#sVlPM^5e`DPX~trqV8H4FZ(<)MW}c%& zWi1qhE!C8xV0l$V+)?GTp2j2homGl!i)`mNz1L^Mgah$Hp*IFNOfnP91GAvwOBPFBYk@b00bQ)zivm23kYSjIe&A;mLyTTD{M!-TK% zaQ9cbw>*U(V#C%!yu5MpXk)k6@^XvaowZK+5PrD3Yvt0B3>yeU;M3UvAN<9~7K&#e zno-luif!1H{n|E=q-(Zxqq47Cx>@a-w%)1W2fb}|plungnnD=cun2YRiUrSHrm@n6 z5C1*l4uC22QO{qU4Qh%01!jSU1GRcv)#163RWg(CA(yII4H8-#*y;)`#6L4DLqh~~ zXcS0c4$RRis+?wDRA_d>!qV)` zJQCs5a`sjc9T-OShdy163)QD~Pv&|C8M zXTGCOtfLOPgX`2$=i8nuufvU=__sa}{XXt7^udSD&);?C4-S{j{QAw{kRrUqKqU?w zd9d1od(M-GAAWM`JUTrEJvca^EqTdW?fKC+_Qg46_rq9ZeiYG4E=LI#fd1!<`{N^f zUVAhRvjh8uI&LrigHNx+AA{%bEAo*dHAU)*s9TRW6!}<@CyEf7pf~a(f+5TEsHi=z z%0rrfzpQ7vO;YBIcXySi$64f+Uv1p3@*-oApxfG%zFCyJ8$~%7vB5?0iu5iU0rr literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Initialize.cpython-38.pyc b/AFM_thumbs/__pycache__/Initialize.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..293d572cb09bde0ee79c0814497294b4bcb9bd5e GIT binary patch literal 4170 zcmbVPTa(;I71n(;n#-AHlToq6ykdb8R}wkCNC6LeBbm!Y8m@oZA96@JCVZ6+vOy zJow><-u)yC^Dv3uO-6Cfcwg4DdddIeUEG=c+X6LLJp2o&T-)a=G#!mggRs*w&Swg5 zLP6x|bZ^Ll(BJDvZ0`qt&SFXZy`Q_+ue&#I+`PGWpC^ah9}dI#aPNMRJLb>J<@98G ztL$+;ViD%yG2Vwt@^wlqY^&~r))Q!h^yg3^ybN-cB-<23^Q4oqVhKA3soCX zQq=-QmQ~BzHR5%m22qo!MYKlLCR!)z5N!}`5^WJ}6U7=r%ypvYh;9(wBzm6c1)>*; zZV|mi^fJ*ahf1zIx{6*r9C^7z_ZN0M8Swky)B73sB#^m;}5 zdPVw1McS!IZ&ajCMS8O$eX}B6t4P-?(r!iCt4KF0(zoUktzvy&VA9H~bCb(8Aq?~{ z6V}+vu#|)~DW0{lmxf~&iQ1%O%(0gY2Ev@sqxLw7a{rKt^&#`K5obdd=UzTZnXm_p z1wFriEQ~`xj742iFXc%pY+}PW7d7I>6VV_h3lC#I5*7(lVP+{}2%EFa8*uiqsQbe- z3iDCGgz3kJ5fhE9@5kOK4U&^s*x3nVsW-R*HF4>YpE1!agxek)v%aVm(vO9)|Iz*( zQA6DlYecPoP)RfH&cgCSZ|25q0A8aLCH{=J-&0$w|nTFjjCaximIcKt-YxX3W11L)MdPNVWct zUt5(wi)g|BZ_00DlnPkcP?)$0to{VB0vxCrVCR97Ymf9mJJ$Gbp)&#<+;?;Hk#$;= zK4&WI_LdSDTgnq9euFIa7cHcBWQ3V=rae(eZh%)2x0$yBb4$rvh+}OjGX>9DDI@kL zDz;IXi5ztvTk+b9m}*cjvN)6Av<7}XaFFL0WNc8#As7~kvK@10D70NvZU!gYid=S~uSj7@oYlHhVn z6b1&#u-OL#I*bUw?$N^T0dry>ZDu?|n+hw;2w%*UqiMNZ zw_;Pa&~g}$+&32~E-j)}oC>@i8zda47iJPltn6r%hX6`G%sB&gK}j+6hyi%`AdCZ1 zlbK~K6-^|^=feqecnt3jj)XET4^@d45Q62*%W|Z6*xkrRDdSx765B7 zMzh2P8hxhI=!Bk?(Hli1Lbmzn%`!SrPa+&Juq~f6c`RPrpI*J4qXFbz_?9dCvN&%S zttnJzx=w8wCwbA5+s^c|bSsbNtM0DsV|UsLGdE67+)>5?cz@^pfjdb??h!U+$#54N z{_1Pj+;o(?VeIBKI+rWboo>oC?#kA1u?f4fBb=%9+F3bf|J3K9-^1>Q6ZDSzy?5N{ zt)2Pz!}4Qfha$YhK%fBRxwV*rYwo?Z5lcNL$;M63)7EIaCO@JE*2PnPm&KMu_UQUBDY9hm*hv1+>?Z$ z2Zt#?BFwTqj}XA)4`CGsurlu$-3BR(y1QG_)8j1isvlC_b?HUMGPiDXReHXIw^lm1 zf5iI7*EoQP5cJqT%$iZDs4u?|BQC?W>vEKQ&8xN_S2Bhh}Skr@OBG4QTLJ ztJzeWhzBru9sp#dc@zQyTO&Z}tQV7cAm`%za&_!3RtKGvX{VrVfu{4NGcLak=?jZa rE(8%Y#LA@5*CJt?{q`^kMiG1GD&ERo0kKsZi9h$#ZNvVy{mcIX;q7@> literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Linalg.cpython-36.pyc b/AFM_thumbs/__pycache__/Linalg.cpython-36.pyc new file mode 100755 index 0000000000000000000000000000000000000000..c82be489db3d6d651e9ae6b01f31085116ad724c GIT binary patch literal 4383 zcma)9-H#hd5%2E#^tX58>}GS(X~G2#A7MAi?@V1fGI~#4EZ7B>n>4_(SHEr@ZrYPyDKTyz4}Y?!21ns_Lrl>h9`a^?ulB zRKL99{qFDYGWK7#_7mXm;!9^B0Sow;^{5qNHsL+awNCU5=!~&Bv3i!$nc(f7t#}K( z({mJWgLiu_cqee5vtA{r1XZ-vpcd58)`CXRL|YH|Bi3!b!mR9JmlyUpiv95rTyr>{ z9z64teme69VY;r_|HZ?5`#*!GwX(VQ$%DYpe5f{7s!xxOCkMas6MtaP;P_p{=innb z{Rd|(V=veV&y9>pj@EpEbw3fwP04ke@sY?aP$RcN&D@Fq2^#^M-@-<<&|AvJRyGc7 z{*bw&iZn2ytvC~$BkfW3gh`{ra#uQvH^En=E$t3F?W;;hI;BkgHOQ_s-eFpo*R$HF zE~~OG-JtCErX#(o_352I}N_INt*$LSp~D~B}}xo#zXJPf-csbGkL zkD#*CXc_kBI^r6IT?bj8=gK#k=M@E&&}Mfx3+r$^^|J(Lz>2C4@4-jcZxl_<&->59 z!J52S$+gn<`n4N3i`JU)xli21w_ z3u+eyU!qy|#9~?S9~XRp4G+^OC`<(T1mQ))iQlWJAo|ld?3D{1Oye}`Ipu;^%%ZTA zMjcI;t8f!Kp`!ifiClp;y$iyG%U#hHHn-1Ov&yTY&g;BQf8boc3A;M)@Ga31mqZ)f zC0;jNJGqH5PVsL80^J#ffBypm+0dI|CNOXS;Eh)C#Y<#v2C zvqz4`JRqG5>;d8_>>=LGDx)e;${7NKq%jmjK`1o@{>=}hxX(WC<<-oURcLF}k|+4O z@~Z=zYQQG)X(+_9WP`Bj&n$1|t-LKOqlUsJBQSwYO31z;Ka+hK=8KnrB@kCl|rc*0Gr1AQt;H zmWqm{s$!{~?Tg+G%znE1+$>jyn@TIzHx?_Xs}UM!>-bt<^VApj5+k$%l-{nRZ{ZM! zgx?o;Rf#X9mv>91eXnG$-RrjBp2Sp`l1(D?8b~@s&J)=pvQ6Y8B0nJVLn608x{glc z?~vksA}V)PLVrM_%3{jcv-?|YL~)cw{+NoaPTdzUNPiB(4B#>{bRC!5z-?Q+MGt$O z(M@Hu;*;ALYd{y1eocG?Oe&i%LYpx{W#o-e9A%KoILeR!n2OKN%#nq2u}^@5>D^Lt zNJ_qd>+}opbK^v#Gv8~nu-!@LhlJ=p2JGJ?+&~LWoyZ5pz zjI(GOU-iNynI>Kod-Njm4x@2+dAYkE#>4E$n;vRylzQ&Sm-a#0~ zh-V%K-oe64!pZbm6c0T-q?R3z3W9f-OebD;6sjP1mzTfRcX?hprf+x_d^e$&ez#K? zQJf`op?c1|Kf~nXp0m)50+_;z(%6sj=!}T?^TPW5QJ92<9fadB3k!1+QujEF@t#X) zGy|jI!I~w7;UAW|uvb?*s$eQid$m#`UyWx9*;EnU z8XSd#C;e#R55xW}nc|h5MPd4HtSkK#gee4bQFl$}lITzshNkW|!I=v21mEQs@ak+E zO}+_K6L^w$O*rIr|@K_cwkL`3K`L zRU55dLFxb#8(!*xtLndkO*QJ;^3K-i-kwZ@<8gS0-aaXn2#Sq9^=G)Z+^g>1{{dN{ B-s}JX literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Linalg.cpython-38.pyc b/AFM_thumbs/__pycache__/Linalg.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2b7369bf784be3977208b9d50509b394df3cbb4 GIT binary patch literal 4493 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-38.pyc b/AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e239c570ab36f732783bec20460677cc21f3406a GIT binary patch literal 7061 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Omicron_SCALA.cpython-36.pyc b/AFM_thumbs/__pycache__/Omicron_SCALA.cpython-36.pyc new file mode 100755 index 0000000000000000000000000000000000000000..9b1ff5c3870683b8c7d7c1ce3135b08f4009e838 GIT binary patch literal 7321 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/PDF.cpython-36.pyc b/AFM_thumbs/__pycache__/PDF.cpython-36.pyc new file mode 100755 index 0000000000000000000000000000000000000000..93a3ea9cf04c78d879f23a302a340b6253eb7b05 GIT binary patch literal 2768 zcmd5;O>g7I8J;02ilS**{#JIK4Wl9j+`_WETeLv2FdAUH0g5zOG>aG@nzFQJEK%l% zJRI%X0(nw^COsKF^%oRq5B(|m0lfCK_dOJgMbT$QcC54kirz|jX5N|idB0x{{b+U7 z{q?kcYWa0CHu}RXeOWR(|T=~REBJWUV{ZwQyowiTajLAD*ggpTAKEhWJxu>s;#dB(Z*QYC8dG21C0%~ zUfFD;YGOFdsan_c@}DJnLayoOuPe7~DnFF{Epkq-4bfwprF(8)Q}GA3bwj;n+f{3U z+#zh^+yM7y(6^Fxl=Lm9ORAM}1$-0yx0ipG8zmxqLO%a~<&`$ufsf{RbG)VU#CGTK zu(Hc0>;9Bf&1-t`+Y^$Bvc%c7UwfhrPn6-oxn{yRWOhtE>0j z8rBvX?s9gko9*4`?r7cU5p-D>6;`%x^1B?xqK@LVs^Z1#6QXi{Ze5$=Pyg>xA)fA> zRO?vZQC*`V#d?peqeo2fHG3C3bUnK8J}U75neAjgPH*#Y?>1-42yk~woi(MmT-RF3 zc<SQ8C^yu3CV;tl|EtYQR&Ju7e^YIhTjTfGdvgkz&w%hTZZp3%H?-tK zh4~V905E;|{bi7z#)_A*9D$~nm`oh}g}gaFOgW3A!{RLbczQa`Kp`2`<&c z(>OcC1sh6re-_K+vnNmcldIZ!oJ8p=bsr38(zTbDB zzH(qoG?l^aVd|%OCZWhb81g*jQe62n&p(*taVCp+#{F5#KajCZxZit2d$Xq6Ve^Li zH4!R%fe{vg6&6QF&u50;n|0VUO|L@jp2~Rdl|s$z@Pq!*LpC#ez#I(n>;)InKVUp7 zVtM61Iy&-knj!^7;s5g4FFx`QE~ZhUcr#DQK4Sd|JL~zgE*5$2|3Gd1K_pdh6U5g; zZ52Wlnw{-`PvA>LY7;Kh_F0@rE@~q$>Shub66q4^b5(EZ0%cL0gx{pFwiKjpOazi3 z8VY6=xsbIv$dlSEq^M1izpTwPx~$#XyoJm3RlWW)7w2&{TvFQ*Q8whYHHqY?w#Gg9v-To0~ZY#g=mU!5;%x7RMid| z2r|4}ELXv*#tc&p`%%zHLzNPWzl&h|>Bk>_1bw2AVKL!@MIQw2ota*rQrq_I|SIg*{jtL8fV`v^uHIKTU zLVM;;!w25A9O(B94>mm7#pqD+V|cvZ66y*Q_|KAvKBjspJ^jxj5l5#9FNC`5bm!~0 jLpQgU*Qr^WbatG_Y0jnzKfVvCqK(NxWbhDn@mu*9+*-lj literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/PDF.cpython-38.pyc b/AFM_thumbs/__pycache__/PDF.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..615cf0e2af549b88da83ebcc4a03dbe2085a6a89 GIT binary patch literal 3005 zcmd5;&2JmW6`z?ME|*J+qP`V7Q8o%vKnX~xGLT*jqXAq6DB3`1+$2~u*seGua;5#C zW=FQUSOP^Iph-{q6QthqU-ZzwVy`_J$iYBQb(^^F4MmFy479z4)Z2M8@Atmnj`-V! z1((3*H|Omm{vIKJ$IbkQ!RF^c`2%{7V3~ZhL#xF>oE<$3Rq(;VuSKXsIBL%yMG8)qW+xAZ z=gHAwsJ;iwM`2&)eY80HtN~L8vVihGa6&XWp{gb5S0v?veML0;6FH{B68sBCTbEqd zPV6iCgiVO9m*feZkdh3@DO11Kj&6wB2GI>5Ky5%K)19bq01`5DJ_huqdqpVvX^O@w znNZzA{s|Q>ppjpALN~~S={E3-;K4Fn2RJU8x>Z^zpQ1}{_!erG)bI<&`w}49K#Los zWUzL?VofYfY_UA413AK(G)i)xT+q+InYd*gV?f`lW^aentLYJ zK*u20iC8{mAblTfHPa4i&m@~<(kz=Gw?O_(FPD(pee(HFCauyI>kyrFvU0hK6%rd) z5ZlBq>tgd~WKzGNXP>2M*$`{S_OqGAYhQo)FTTF{KYjhp)Zhm(l`h7FwY!Py>{;oU z2p#d-m*iTyP}WN9@%J);{fh7hJW`%Vb%< zak*74<9V6_=K77FtduJ-#lM@ZmaCU(x3J{A^1QxbeJ?3f>!~gQC_u8OcGP&aNt0k;j{A1t`a>8EzATen5}nCF#gi z4yBlZyFwXA*GX)m!JQzwPJwSMA=0!<3khvG7o*qh1L`wE`rp9hzd2hMJ z=BLt&W%y8nG|Ii~TzkD<&+EAdPaW{3@LDg{28owssRlz{cObJwYBlzXme(C+QL6K( zkY3U7x;oOa^tPYV?V^r5*gU6RMHH6YXF=}sAm7`2P%v-1=!o+q83!gjY}NKtL=|@M zPH%5t6xKFiy8SGL5^1k1WSU2M?A_Vh^WZdr66Cq}%fnxM=ylJ|!x&{n3w7^^-bfs8 zd&MR!`qX zftfQ~Q(-!g6(5CqSn(4makYZ~tZyJe8YZ%`^Kq_a0uUJS${tAFeE`AAAV*RIY=3 zB>U4j@ZB3f{?ai7736WI^B_tCtR#*6MjV0)Sk``P3I?N4KfjqoLO^&%VWr6pbq>%f|~C% z6#mXsSbwz#k7};5y-z|Fg-5Z>7589Baqi!lo?p%khyUE&UhXfY6_=9s&&p~oOTyZYS8G|zXq|?HMsr>dIm7we z*FC#Kx?6TkNeGNMqI2-sz9qMuj2v?catYvbpMoR^LLl%l2n55*SFd}9!(DR4HA14R z>s43PdtL9ns#n$XdZCd0{?Cf*e_5BLf0xGo6yR^+@@~nJ#3UxSBrCqlmMq$erHH#~ zsp76#nz-whj=R!IwbNEwCK(mDVHpC~fM=|Xz;)nRD=Y96@SK$scp7-#$_v~8Ua$%R z&j2r4MS*8q6YY{!5_qmvZda^|!1KT-tx16wfLE=mz>DCYvZe$+0esq;7I>*O)1I|v z1zv8=wdbvQfmeVpSPKH51iol33cL#ZlywUD6r283vQD!ZHjDciHpk|1H`xMP#QiLj zA4tom_Q|C8m*r?;qt#u1>~Q;Aci&@y=;^r%qH~jBz_jEzr1s`?Xre*)vMe0`s-K>ecRh~xXZ4-ivvoRy1mN!DaT&I3;={2ZRt;3CAI30T40j z$nJqgbCJx;%S`)Bos*cprFcJKsW9c|{Ctp_kpjJ0VCh|XM$Cv0XW|!|6U+!8A80Hy zBW840VUP~fM7b$p=8xwwzMh9=x0F4}`vc2`88Hs@LL;Z%A)OUHl$zzhVEMYTD~H*^ zFa1hj?9#gXS(rP%_aGbOm|9nElb){`so*WV0IxRAyC*+7{qT9V$`3~n4d44YwwXKuPj$#M zy!*7Ks)_xkg#D@~u;0`R*pGNmYCqyVY(Mo8hd8%ut5SH_hYac4hFM9r6zECy-eh^5P!Hh2vM<+>lr7hE-ar0(+G(v0`ce&n5eR zUhMz56YT%_7uf&Ad(!<+yodLHn)W}&JkMUEF^3w9Bke-6zO?aZT$MsvIoeJ5hxmE0 zFeAlrK3qifUZ5xN9Os(n*&;g?EXI+3SB2(9P%p64!Q!s6XYjp)R`ViG7T{%4a7vsX z7TKBb^x#Tx8hrl<`s+AFoWfo-_&*RAyB2eGG-ih2dGt%X0rhx_orQK4Jzc^byLIrk zUtt+x?;9cBT&$L_f3xI0p!werTTUt^PA>=ch~FG*@bb_uC)MN|n$*0^mY%lo@YHlu zQlvjdYjYXrwIfFv@A7!|PCm-!OaIUMUOtIFc!MkK`kd5!g`GpJy0NA1<+uXs%j~A0 zo(J_-LR|rUk$nUC!PVv}yTC5)DplH}M1AA7#4ZWBKLK{aSqA^BCmH1n=zHxX`f!%f zrjep!7v%VF*yZp{r!u0E1^$^Whi9;l5$(W5l;8QU2Qo6HvhYZ^X?O2xh_dB;8_c{}9?YmN7iwVJD|*H>0oubHpz{CaJ(;hAmM-|RB;iQ}11c*FPI zj@j*)>yGD|-MabUy=&%&F87c%o0pzZacRX|+jLFtdi|E~5x>*fHoN|&%gx7$RL$v_ ztWmFnROj8ciHD{;phVbZ=*f*$)cPE$sc%w7H57fr+|m1f{gqph+~8C6CPpLy8gRCC| zgPI;}K5BZ`AqtJMtVp}mEbn%dqZ_(GfYqs3FZ+82*xXHSGbjeos4eFB8 zz5Q7N=K&&}H#Ro?NF#wr>GvXyb)R&0ls8+ETyOjrM!A#z(drv3uhzpz-rP|>@*>&B z?cv(pFJ*H_xnf4ywQjGw!JXdbb|km=v!pvix|L2lO4qymiNjfBtUI+W!uBr_!yhQq zR>XqfFM;sK;83JTTK1YD& zGb%sn@~uW^V^jm!jx-cyI+2EI4CA!&qcrA;mK9&1mfquyj?Z<%Q_QV(nH!}%pZ9Bi zlFpunVU<&{Lf^65jgGiE zgD5o+6{RS(9p8-|yY5f{Bhm+Uw_cC*?f8abkjtVJrmpSyQTlPW#t*+uET4ak?#2p_j#4xLBrd*QI5(<_Q39=Jd`xH7?KjY4t{jp?uQnq9YBx zZANOZ`y>+eC@5$->v*xawVkvkd))1zIwDFQ=x7TiEKc>CC_QYIsZ|;0ODbTdWx$1q zLWxyCaYkS^m3pi^HE9pgT?Zk5C)hBg%AYE;v+ z%CR@FMO`Q+Rl4hc3I~CX;UHqcC>^tToVJFQ9aB&`z>`j<1?5@2IT+F%*be8;wlzyk zF+s357)`9_`kYY@iyc(?;&F~iB`j7^h>#_0f4k>e3kS-c?Y1B~w38RGGD22}6=@MB z8v*Xx$_S0*CaqI~YZF_-<%#IHiK?;AL(e@ci?wc}gtmb-l26u;sG?bw@s=&#$kHEB z@pV|EL;s@E7K0^P9R=EvVhPc>?t|q0H@RairIeJsQc?1{hMHML*0gC^Q?tMfRL}r{ z&&ryT$7QHRr3mW0cs7JZ9efIL$6P{coL4!JD5{!Tfkq7yDLJJYsv%cp1JZ!#>qz~O zDPe3?KtuE`AX+JT8nRULJGk; zO})k=nof=3;F-p#z#(T3xS?yrjSYbq>-I;O(XsA(ck5_ih_bYE0a znX!N~m(cW>W&9LXRw*kKe7fM%sH%!H*(Zl2j4g@(Ez3Sv;@%;N93&!^f3C#*@aePt z<5Zj3lX=C@HgnCqUuYHs9q)yjVVLSvpQ09tDrgfyYFCEbEharc1s)am67syXz{6c2DvC6!+#~AtGwi|jM1;6nydsmD*ebFf&!aD zcA@e+L2-l?Fpk*(UtH`mtKjTEf1i)e{romI7Jrj~ICR}0>^gyO07UBQ>T0B{uI^KW zisaQDZKc=Q*wI&-J$GYt2IX(y>D@Jc9=ByB(iw%CNEe|sI`YW3yef`eBJf3NoE%z+ z3;Z7Bd764MhGCt*M@`jXEIv%A=>Et<-lX^r({UQDv14AU;fX^X1rq*!0)I~6hXm>b z9uU|dut{JI0G+LS{6lI!B=9!TG|zRn_;(34C_xdY5gmuU*I(mwwC3;9qm<)`H%~h_ zf*{uOKO<^p$4=TftIdK8Iw#a;>awH{Me;3tBNRrFIn_83sEAj3C7Vu6VU-*$M`*#8v15L z2jW9CL7aIyI>ZtheElaZ{alG*bciJ=p8Wlx2=r_p2hrh~XA~Xye~v`~cn_AP_;n~Y z5H&~CBsL({!8_+EHZXmIB0vc?DdQ?J{WjUB(wt=Zricc@|7xtTtB_Tw9>t16W;VIc zjeKNEVDQ;t8sCQvTp2dON}o#p0>z_uA&>Y#{<#eQ{Q1Z~Bch=qXn_mg9`RN0K76Us zoD8zm8~o$YZ>LxVKD!VUnrHnb=mLhZo?}zO|HiHJHzm+BkS>rkzRdj!HOLF_r5UE9 z-ls!CrZd8BN|p}1KbwSioVkCLCyaAqA1jFW2|On71mFmdc%vTfr|9_(!04+k)|~i) zPAu(#K{f2e7>_`}np?mPOPcT%(i7FO)~xgLt1U>-;Yu6MHRE6}v8SQ}DRT z%4#GJp4yOKW^Yr5Q|q>ScRq)RCq^LeTpG{7lH6?NcB@-+THYNXLz%>#^8xj?4Y2l9 z^1giWz=`u85!c9p^MIPba=x-<;sia9w+i-cBxn*ev=_0IH$4} z7X_#CnDjmI0~Qf7qjCBg{j$ar(T;DHB9sBVB literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/RHK.cpython-38.pyc b/AFM_thumbs/__pycache__/RHK.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b43c4be3a8d936e62c95e0328aa497dc27f2c100 GIT binary patch literal 10117 zcmb_i-E$k)b>D9+fCUHw;5Q|$BwG??i=yQZxf#WE>O^%@TX8JLc6Z`pmbeQNB))Wa zX_3srNkcnH-RXqsXP!FXThgaK^$*BH-a3=X<34q!osQYRpyOuD{?6T95R^!n&J-Bj zJ@@Q6=iYnv-t)EiPN9&K@cGs!#g(5lBGx|}`c@;nZWm%G##N?Lb#8=soMPG3g zaaA2vTs21%SKZNZRa!_09TxffD3@DPF27~&`&rM0v-cA=}Zc^)S7Bf zJJSLlZ_Tu4oml~w0na&e0wg_(|ZeYG`8C6u6*F~+Sl&B$=tvNsyK>ja$v?&%<|f1d*v;cA0zX7Zr$^V z@$J|DwASAAgPOP1^aEfjgn6s$H-l!k^ICVa6L=)An#v1EUd?arc(tul@Y}#o*4MoH zMy=U)SG`(~cY7WWnqtUGoqKNJ)nY+{fM!xXhW2}2JrHxY60jC{TQt8?tJ!f|tF>Os z?Rd3DlW=1R4wn>FX?Cyzw?*@Wo@$ArEKH^Dd93!Z8LWZR9AU|hiY#)kt8ea-E3 zyjGnyar!X;==i;cpYNbqmHG;k`)VkEU3&lZz7|O9@<0itP}^7fdZ;sO?~j!kDNr{I zev7G~RGGS=a7$2Xp|me^D^vzLL9!%E58iozJ|4Sv@9x3x4i68P7mP^h`jOUigSALo z?>0M}<`L;lpEY@8xV@g&VW7&Q3*~kBcBD6&EzftVEj-#|0B>Zryx~cUQUFZZ|ut zH{aS0*18>`Yw=|Lo22#>+z2+k7Q}zxaUc7t))UmvkJ4b@E%vsfeABPd7Nps{j9K`T zXe33`G})Aka!IDECFf*A;g@iy4x=*s*nr3wi6?W*lB7V|g*F3uT^Xo>wodw0`f^}| zGLv_epBDQHw4T|Q`s%yVi_*8Hx25-_z+BG`a-mF5f+>BCo>i#P^ApcfV>;75R%aw; zY$*N@Sf+0T`M?T|DJj$k1!nHcQ_?PY1DK$oI2dEu5d5LWa#La#>?;i1{S0AlOV}-^ z)0kgO!}6HL@0iukidkfj#s+U*$S)1XLz5L6%D&vs1?AA(rG5HIKY#kjVJ^%wwV~X> z9{!?P3fkhApw&ic_v8n&r_ZBrrQ?TInAuSFWdBn()-Q;)7LL~X1PR5V1dWx3`Y0y) z7=u2FXVAykm(T~%o>d=2dt4vNgX?U(U&6dBn%7?T{k8shI1YPZ?kW6JSdVg03CCD@ z2D>aQO<@OhEMUrMFJ12wbW%A3O*N%SuL13&YNEFZ%&&R|y-j=xy%FtM^+vSE^`<^p z2{oaciC8yu-f+6Ar|V%??oUExMiG1SKsC4+KuNO?3yRg7`^iJwY&!YT3) zdm8^O?9tR9$0o=gb?yRR6!`y6@RI_+2)qWo&Xoi|CGeBL7X*Gf!A}!D9p!Z0^rwe3 z=KAy?Cn#r5vSi2Pnd>uWrX?-Ro+J^vn;nk+B&xX~mAO8jjC-QQ(K!xzo+SC)nW)aE zROwY{>BJcX73hCrSFTEIt_mMhyO8p*`GI{p-@Xjmiz#h-Jp<3Blor?651hX1W>VUt z(;%R8WMjmRrL#Yioc&px{h2eI{n;;Z_KEhaXP;<~pZ&~(KgWD$<8$BFSnN~JCwog9 z^}AK6PrF9D4cidk59g+&*rWI7;iu>54y?xI!Bgx4v%~q=r|+w<7W2S9%`S%X`^uil zcaD04D~KV^h4V}b&xuH3o?Ysn56^?@7r~c)g(b!Xc&^-81jApZ^ zAz8&JSHpP`L6lie==r5SRxI|&7q2N<0i^!=%se7KInqPCV(hzXsXopsDKIr@{TjRS zsAki+=(eOtzmL@Q1w>>g&N4pP@l!kdEZ499Kg)aOEb?Fho~6AoxWTUO%k1)ox|ies z3G6co_Sy(`5qPn4f}4XSw!p6MD^;Av7<)%z&%}Iy&bTu`|J+$-`6cAtI*UBSF4`ng zckKT>|2ccMf1y(z;#A=Nnce7L!1=B0%Ag|5Z-VDT8Tr$=utJMug?2S~KL`CuP~F@x z_AGe17uH`C-q7OLPvN*0ycCXy7j_lIPQMCnpD0z^Qy%<^e(Vx5uBCgC!dDKiAdTRZ zTO3g8cknrKu$}Sy%gr~D(ArB&FD@=Ey zT;H?14g3C^FWB$IiI08tF%ef6?d3Jk=AOUV3Vfn>JKJ_QSo64@q)T?)?bxi@XaLpV z-L{RJwzow&vd1uz7mKKGa%8Q6O{r7L`W1Ue-wYZzUXJAEfkrDqRwV7b_%82uR&7e- zX~gczI%I*-YcY~VOLDg{>?T&=+DMvLT3&ncKqUdBl$}+YbI=Xkmfb-?0270l9(3c| zVD5ASF-ITSqz$Fed>uzF5ws>IDkR>z=ig+CS z8A41`^Aws$=grl%Akv6AQZ{>$#<~wXJIYsEk=$s0iWz^F`QFl37N2YMQwdKKpS-rC zeAkcU8ZPfHAK>vG-u+Crca&%CD7W10QD)m)+m7V+0cDg2Sz=N;?I_de@`o;Gk-6g5 zHwc1Unv`f3RDOeCn%luuGz%|tnmwm9mQPVbbLXVVX#8Q9Zy%NXJ>KjDoT?9z!Mu8xd6D4@O-J=sPv!^5WudMaGsW^F+pWd^LA!4VMZFk-k;y zHX4z>9bZtP@mOR)FKsu7G9PqX0X9OUW8jvD!-UcO%@xekb9sF&(*3~Y0k6^;G_1~x z@>JugZPhkWvq?JJaYqxVOj3o3v_`YTP}XR5F_4DQ)*`jneHe)%5d^f{6)Y_7Z701- zk9$3rd!nj^APp6=Iu+WS@%S9pM7<_PmAfn7#L>jSIGQ!V z7-eEIpVR(waw7stM{rE*ObX27a`RB6w^egFcekBsB8m}$yvgXn`d+|28ezVJ(px;w z5w3*9DGCLS?gvmibg$QLVl1K*1IVY&ra3nmQ zu#T#z8p}L(-*ot_NR)x?S%{XSJh)7lxv7ZtF$xk$UCKqpdc zA)41cp!~P#3~Po`QY@vcSh|L?R9V)vNm)}-o;oyShDpjTM5U+@PnqtYIP>Z;x zRMrT`aoEyR8cijsG4~Lsn2$?R(z}mHQZ==RxoC1(5wp}xNK~ZZJTZrno_yvRLT(9K zh~*esiAr{dv{uY*6b6-%+`;-W%Ocj3{zm6Y+OZN!12RV7p)P?Ru9M(Vnj`HKcd8A* z>Jg8kn4c?(^0}d!LMO(dc1V5DXf$G~3DPgEBJI=MrWJa2=~`&!C&Lz2G1LpF%Cf0X zt5nXkRE>D#BBT{DgX46>muM4Qpp+D`muLkecW4gDo!s#|wC0q@q}3cr8@ZD?^$w&> z%4O{1oSZwfl-%g3qp~r(Q)DZqRun7L6uK&M?sEee?0jfa^mK5>c->U^CQenI>~s1d z_etLOHT?WP!l4TlCL^F!P(UxE9Hw8EYd)6rG!=w zL^+t5a|kVkqz_m&FsMXK39q2j1)WCaVT7I^9^)`KB>oGQdm_gh$2jufh?w<6j@k6? zgSR(?#>SH&Yf^~E|?D`RzZ>f zT0bA=2j@`6SN0W@y%RDzpHN367_U1LXxP90PySgU+si?rLa;nN<|vLksC|7RktOfL##W zR+!sU{C`LPdfX4536)S2Da-!^&(bVW3dTHw8wpR97oiDNYJa)&4y zGi|ZgS^Z33T<>|S{6(VsDw?~?{4y@TR3e>`LyvS3z(h!>L?A0di710utOZZY-z2^a zn#fE8B~D&7QeDR4@Jz)pCx*=x@m8thHd`Zsv(fZLnEWjg{1!FzW{&?EHLKJtQ?o`* zlbY|K!C)&sf0w%NQ9~9c(tOX`;NK+Bq-0CPcRIr7=WlV!1o$`Tmf`whl^GX79ik`x z4q>x9wWN>emqIH9yK63#VKiFJUJI}3=(@>xnFNhdQ=z6vO&-lcDR~b^F($tNOk~FI zP&+&_MM#9mj0bdMyw|J;n+R-ah9b0ya>@Hv3XF~T9c^;mcFcB@!p_>(5ZdNll0z}L z8|Au)FOx_=AHyO|;C}_0N1`F#0q)qQghM!Hm?d!?O?_JP~}Bwua3ao1N-bofTHnJaJ2l0p0Y*DjK%?>r+ zL$f1F6fZUU2lP&#e;>`U_u5nmpgZ^R^RJ;{wPI;zvc8568g2=g=L zfp$MWxC=V}5qM%VNTOm}NOo^QiIl~qNZxwngh#nMl!Vs1?cOUt0*g;&7)lio(jV?z z9Zi*!Bzo~qt6O(l{wn}dPT>)F2-f9=D@R^{{{WaH55WI|y7#F0AvF~H@m*?8sG0DO z=*Gurl0rcb|AYv9PG&zUi8_K?f3Vq%|Gy%NCL@kuX#S&|AZ1<)Ho73-28tL|(TSbM z8#E001O8)b$Q|&XQ1h46d_s-zDrEL!=RtL~g(CkMA;@s^zoF)Dsrfr<{+^nDpynUZ zMENaIJrId(l;0ldpzcBzSr})L;!_1iU~J+R4dtY~h34DzaDEOz64qDyJ*_TT!jr8o z;(FwWlOmI){3xf8wS|>DG+5HZveqJl!+qF)@iqUqm=UvFxP%hWwjV#x*Jl%w$x?l;8WgM_C(hF_-t zE&0O9a(Yy}Kn>Y-;fJG%5gC6n{O^#c-9_b*d#}ZR2;x*TirsjHAgX4G|D%ZfMK}<# u@{x086NxA$n0MM;w%PJtnFGpy6%FN;$(KCQ>EHCOYEGKpm*}hDs{bD-v8%ZN literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-36.pyc b/AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-36.pyc new file mode 100755 index 0000000000000000000000000000000000000000..3d07b781d61058927775df1b7ccabf000946353d GIT binary patch literal 16230 zcmd^mdvGMlS!Y*ub$9hctyZh`nrH94R@$A>%I5!U*_&mU|^s*u@6eAfCI~5F5sG4;x{-@Z8IG zvpsn3W7=Y9Z0~Jqs`)X^>s_hVuiY$iYjXBERq@S6^BPVYH;a#Y3YV6%4+a>qr~lUsR?lZ5-%0) zk|lMQx*$5&5iQH7y7rfAWxHIgQXSDymTIXKWG@?uOj(Exl!kP#C<%w2_c) z+|cz!(C2SsvV_J=Pp>yUqfxZ4 zdq$;Ru6bs&Q7zl04V%XR@FL|VD|0VeY&1$W#!bo;@#2U>ht>I}7g;V>OHB{mgx+mO zqvbu55~wM>IB^!SpA7N+knq--8+3!ve6@zux(VR)%BKUM_u#>IGyROF#6Bf7idv?SfW(WLIBiv*M*&%kA9bxyfQ8vcz zTQOUyPVHNPB?S;KN(twJ*Cp z>?m>?{0KWnX>44C9%9Eu=!6KJW+z4H0TEhY4~o!3BJ>h_ScD!Cp(=Y+gdP(ihdtiv zv9pyUl{lNAbwlw_2>xCdvj}nRXSOnmRYtU;!tM-@iFCB1O5Yj2PozKTr+0*@wwFWf zsX&`Q%}zn1189v1fBMdL4Xiu&v$qBE@jyO)w|wmBK#n&8Io`Nyj;x$FY%&)b47Jki zbXx*{wVj{8`d#MkU3(R^ZPzc#Gj5tq4Tap^AsUZIQSXClg~_-X_RL6#O{34E&BqWr zgU}3x_=1?r8MUrKFEOVN*0RBP8D|ed<`D6fJl4NHHtY6@RU_|4us_eudpf`7g_AfXJ#he((?W;NN*}({1)+R=0H|LZs=;NrMVh6T;Csgr{wYkR*BJdMoiHy$dYWR~x5ZAyFhZ8gfqJHH_`ptHs-xc*PojvRYp%R-325 zv~zQ+-^!2u`H{a(j`y8%jKkw6mz^G|{=(b~GiMhk{_V>1dm)^U5}{X;ZTPM3>KCv&#g zEODz*e;IVOUK=l@Wz1s9Zs2v+E|}-m?Z&!oJ?L`}dD;t}_M#tt?0Z#)+Zo2#LV^HVsrUE@;c z(beOZ#wMKD(fpz{Ig$6YNl%-lCFFtS+y4)L{3%ErJI2#^a9Zs60Fgl=G~&Fzm+SmS zxwhh;X*N9rr%JRWtz&fh^P;?I^Kyfa5I)LEOLg>{LCIcvvWam?{V>CMoqL8|s#d+o zQngN9&Wp8`k{8DD$cso3G@m>JXU&oq1En(zl4va8fK{y*Z7;eZ&fQ*gQ$AxGR-?R8 zs(P_a#Y8r&`tq_D*%Xg31bYz_1WC!}Qn6;OH(32;DzSlctQWgkui7}5dzsZzvANDm ztLR+v}$$RYOXgLb#9kfA*JHQ(Ue~!Xc(h~7bxdtBAq*fxA$M& z!k$Bp<`LSnl2IHwqgoVtfXjwW-3$-vDb3U}NSDv7mKI@CJQ30}NKN2B ztqtNQIaBLQAqi=bgCvmzl9P@|S>Oy)9C?vnPvF>_)6+R!3;suS6S)lh#L<|_3!BiJ z4$P!=*B^9GiF~A^{2vUbRZU0_Sts>GO-MF$)pL=QmX4vFk$F+xMGOIw{GK5EDqn{Eq&vt9kpY4nTPRYOTW733QQ)gh>gQ8ViT@` zS6ZEqf=@CX$A}bzA*Dq*L>RAx#t@8v??D5z)d)%a(SkZ53 zZpzx*ZgG~uE3n4Dfb@MrP6{deS)Yjg24eFn_MTubA;&-42S`Jtl70s}QgxoQ4+T;W zLpQ@Uaa=aE5RPBj8yF2Z#HW3(2Ra^c)1YWC`iGe%T)CHwDGYD6W4U>L0K-hYTE3-S z5%1Cb7{%NN;%QbvKXHN|75oXu7;n^8oXB{kQCe}rrQHy?pW<`q{w*@_B|NpuqQ;9tK~+O^GlRR1lAd+Ny`&N`iPJTjnjceF2J+k z#xi_~B9@6TA|(*dlrR1@&etdyZomkc7V9}FCe~vwp)h1YRJ_<3qSE~A$tQMY%I78O zRc5KJF)4YmJ#vQ%-La1EY4B15=EiQPk>(Rv!JF?yu8<)Y@!?1&oY4luSo*X*;+HY7 zxMLy2(rlzP9Sdf{*o8P`0>?X={AA-L3ozL$_^uV4$d+NfW#N{FpN=1_k1Yeg2!2r;_G8!_^;T@- zB^P$KtCw0Pi?}B2gbNEH78TqT7DH|S%akofn3kHW@B z{Auu!wbPhVu}WB2Nc|E~ew_8R5?kiR6)Jnnyn5a*{cFeze12fjm91)uD#a z>9wxdPX(}P*ytqo>nLYLZVRFwumEHE?5#xPlQti=3!6eO%Z^}CMw*7@>QkyL{f_#} zy8J?*tPJdPRF=*k=&IMJ1K2*;=*$O`zrzLpeh|DbYfBZXHoi)OZK=Q zV0k5R{tncy0yWI;QRz23)7b$re%_!GVMQ8Y2NmukU2(sraJ$$ch5KSx+^;L#ZgyDV z{%=>@Zz$Xzc0}L|zH0|gw#erQ$7J8_Rjp@WapQ_ptj^`Zqe$RqOta)Mz)^=?=&>1||MWCl(sL z30Vi({X$lRqer`pjo(!*c8DESxHCI&vPXYU;SRH73TJo4{l3smt~N*5xWaz4EA|Vr z9%2UF>qfR>`~`Mg<@j3H9RD>SeUzP0*za^=Z4))>QlN54cl#zjXf z$lCok!lE_rV-G6aj&ZMA{)-BCKYK{wc8-5JzW%$y9c2$IT=((+C51c29#Ob2ch&EI z5KfKParUUf{&QFCmjzb#z;X7Nz{dE2uGs$>kb8nXF0su=)QmuXbj|gLfm|ouD1Vb- z7eVXBxZ8WBzem_9l|J2>uJrqwlJh9+@KR2-EACGf?lD;3CGOR( zxUUE5@Hm@PSR8#i>MQH;X9Bxdw9N!;@>1^Kb;bU{GbqN!Yl(6o5$Oh&B%gX&7Z&M#=p*6*UGQwssy8kzJ_bl_o(eY_JRq3gu zWjYJlz3$UMoE!=z#W7Rdz@#b}AP|qE%iB;I$@mK)L(5F!cY1@{{m|wq(i`Pvhe1)7LhBS#r|_HJc*K1QG2>{nsY+Vxh5{?} zoR%?YlPuk|%KPlC#99p{O`_x}fjSLtTIi5iyK=f>dXYB#e z3km)mJB9n_9D9cDTG$zN2c4sLNj9fYN$iR^BC@wrD&n8@;~zkL%8x(m$Dcub4`FM= z=$S#*gM(s{ztc_N{qrwHYbV%qKH5e6yqiY(=VS>u-fHd)4!kLA5bta${+iNq!8YAl zI?S`@eNE5%a=xrki*BX^aluFYokCo6`#KPp6e7jb3US%Z0fDziaVMW+FZhTP3h|Ybvc}8MNx|2V#4~)O^G>g{Zsv4n)I8yrK{< zx_g1x9#d;R;u8vS#ogC|Xv?71YomiLNj&w)UeP1)2@s=fI55iQl;o@K93*d#G6OyG zPmC)KdSTF$^;~f8>8M51N4#AjZ1(^V>wb^i^bu8sc-cMJA!EZwd_W;K-9tcZ_p0L~ zKBEx-!95Iw>zC5<5noe?|L7h8;`@BWyL`kyDa7}?_X6?mHUjUIef)KHOW`tnkHRgu zW58|q?JGXwltR469R*^0Rr&!R@lJ*KPwss{Y}e>N`-pcd#D8(`??C*ZkNCJkyw^Pn z#P;}jpO5&WLcHHS)*<5qKH_f`;)mSv4jEet(FeaZ*~5$OaUizq^20vjs6xExp6HPA zBR*nYA+ES5I}qD4w%eE5dOPRqVw|23OKU-c8~mwk9bode%5`w1Mx8*@z)CR zarX%ze$KD$Clms$rw~`&CxZxg(mhS~uCc$GzfE@o!e~3|Y21mvgKmPaI=f~z;OJSV ztE+e+A9Ny(UvLHkiPvyhoNvBdDmCKHo;%_L&Zmz4eB2p1n5Vz?ePSu^UrRc>R1&-u zS4w&EaD^e!E-%3cQrLZ+=nHgX8NW@oJbpij6JMw|C-UUHAgs;4$=Hd$D4@!*AzF~3 zou>mP!&kFoz4;6?Fq@qgnE!&9S&B zF!b~fJ?&(1scPezY$fj}I;q)mm2P#(s2z7Q^KkG*sJ@(U+NDM_?)1$`f7twKYQoV= zV{v(limP|JbkA4It7TipXD-4?v?C_H2qAeg*h<9EbK7@~dFr`36Dm4=a4(Rz%&<#S z{o_vZdKs?DKRpz1@jD1$7a6=Qs$U z{O%9LWqg&brFDK2L*Tw{mG64>A9n^88=N#*s@G^7q8Z>35O;DA>fiQSH;dKv5;`pB z&!TplQT+$DW9jk(lS($rB8_j{YXrx4?gGZNRa{z=t&GZ|u?iUx+bH73omtg-y;0~5 z#@KZmx5tRK_z{|uZ>LEVK6Whc7{~`z>wsEp5y( z7eseYKv-?{Xj_;-I59Di;d_u2SshUsr?(&`?RZ}FDpGq?DsDb74;@p^MWQGu&X6e!hlEZl3;+;)<{2#z3e1WdE~-I|il{JrWGj>COAy`PPO1u59I+}81VL2APsQCk9Cc)B^dejmkeF&` zr4`39FJg3*C_dYc$LJ#e6RZqQYI~IcqNk0(LQt}um{>6opJ~VYHS67ukyTT|x9#KdDFU(i=Cd3|Ce%r8t?aK;b=&KvNfih*Uw>7hkQ ztx3=<>!a9BT8Ne!%rUVB9b=b}x-A3o{<7pm0O-g|sf<=BF`$r&0fjE5X+t{E-YVB9 zCw|Ev);T}jzf!bp2b-I^U(DMOB1bO?5mP2mQNQOhzMS@`lxojTO{%t#z2~ImR6H)0 zG02wlnqW7a@C~$cWd1l!Q8^nae))u&5fqq&bBL3iuaAq(9ve1B5!FzpiACOtPs)`G ziLy&%qFlF}1bS4gV1C6YS*`_%f?A-FCR>iuSgqm8!zai=QEk96=kF@O+Y>O$ky-n<9xnLtr@!>-Kdl zxKZijszx2Q9DHe1uZ=w`?#K(t*|U?+SOsw@T}X+*MQic$%*=vHLI~egsifr-GGq!M zrcgn07#9WU8iiH91mCUe(4vqPD7Y`dRiJ2#Z)Er%B7tuaA>UK}qeMPPgmy^&<3wI1 z@*0t!B=QqPeu@ab!3*&Z6ZvT(A0_fLM1GdY$B2A_$j=k`IFX+t@;Z@E68RL7Um)^n zBELxFmxz3Z$S)K56(XM{@~cGNAo6QOex1l~5cwRD-z4%|M1GgZ=ZX9_k>4TmCXwF* zDaaLx<_+E;*2}W-`R`Nu7bso&mXS9Br&ng-n!sNIhknE4v|dop7u9n^JvR%<8gGB^ z)hxsjkc)I-dvnG-EmjM1tia1ogw*cU4h9!G0oduau)mA<8I4ez7ljM;8|1j~dGaGM zvYHt&bpIdj2#K%>_XO$hW$bvGVbhSlYVZJq-KNH?;iFggoBJe{Nd` zDObw4YpJR(LHZrPEIw`9hkQHJhyD0&xpu}K`fkuD zV`sj*g}*C#L1_d0PcV9YmzX31KlXJ{nHBsUv`%@$q5hGBv*+{hp~ zY~W(HlHeckOM^=cJoX|;Nx);Tt%Hn>Qmlwexe0uv`B@fQB;UU%t`hL6oC`-BH$fhN zE`8>PPmkRQGjT-`S$q3s_#DE_5ucwGCJufBb#)@m!zUhK9WH1WgaH9QRd@4Rmab*g zh+f!%XYvp@;V{OV#MwmFiS!VmrGkG6WGpGYv~GdNx1HoyOPdG(3IYCzh*%K+n7FSJ zc?G1978?w{6fM=7*v9yKC}oGI)uHa5R_$d=ysI_eAI8G<0CI=)C?*C5I+g}3UT|6^ z|0&Azh>&P{>-wQW4n{v;Oz@x6Q$u|)1<+eW}9luoM<>ECm(}-%L zNYygr@Xm#KDMp-08T$em&x-GlrE?n@V1(OTA&9s@Uqv^i=NmPwHxS6K%qK8`h+gxu zfwU>ukMRI<*_2=3^k_+iR+o YqrH*@p6!%~Ic$DksBUh8(*KqJ4|MtLRsaA1 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-38.pyc b/AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac5ba7678195397a091e30fc73eabd5d2bb0d723 GIT binary patch literal 16052 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 LYHoni|Ko|_=jpM>>Q{A_^ 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Thumbs.cpython-38.pyc b/AFM_thumbs/__pycache__/Thumbs.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..394a2d174f91a14b9a63a1ebb1bca865536ece01 GIT binary patch literal 7497 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Variables.cpython-36.pyc b/AFM_thumbs/__pycache__/Variables.cpython-36.pyc new file mode 100755 index 0000000000000000000000000000000000000000..a60a254da5f46c87c7f779a13261e2facf50fbb7 GIT binary patch literal 14845 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 literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/Variables.cpython-38.pyc b/AFM_thumbs/__pycache__/Variables.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..193992bea5099a0a3845eb57914931c8f992f631 GIT binary patch literal 13774 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 Q`6;D2sdga4i-DK{0KD-esQ>@~ literal 0 HcmV?d00001 diff --git a/AFM_thumbs/__pycache__/__init__.cpython-38.pyc b/AFM_thumbs/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..333f144febd1cf9d5e5d927e8a7875ee04d2af3e GIT binary patch literal 211 zcmWIL<>g`k0)-Ou5M~wzhQ}ZdGGGL99DukOD9Mn*5X_*-=(m!g2qcUkepTq_rlw>j z>L=%<>boSCq~?LhMEwW_U0nqu10y5-fTH~LqQu-n)vw4yv&mLc)fzkTO2mI`6;D2sdgY2eFkC% E0C5F3*Z=?k literal 0 HcmV?d00001 diff --git a/AFM_thumbs_Icon.png b/AFM_thumbs_Icon.png new file mode 100755 index 0000000000000000000000000000000000000000..e3324465651c6d110d6a301e2a36e1ef5b87a315 GIT binary patch literal 3396 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 aP5%X>l_uxzQha{^0000 'globvar_configfile' and 'globvar_configfile_path' + + Config file: /media/cle/Daten/Data/X -- 2021/Programming/Python_AFM_thumbs/AFM_thumbs/Aktuelle_version/AFM_thumbs/Config_default.conf + + + Directories that will be considered: + /media/cle/Daten/Data/X -- 2021/rawdata/NANONIS/X -- session_demo/2021-01-18 + /media/cle/Daten/Data/X -- 2021/rawdata/NANONIS/X -- session_demo/Session_first_time_test + /media/cle/Daten/Data/X -- 2021/rawdata/NANONIS/sessions_Ag001/2021-02-03_cycle_13 + /media/cle/Daten/Data/X -- 2021/rawdata/NANONIS/sessions_Ceria/2021-02-01_ceria_10min_550C_10min_1 + /media/cle/Daten/Data/X -- 2021/rawdata/NANONIS/sessions_Cu111/2021-01-14_sputtering_cycle_48_b + + + + I'm working in the directory + /media/cle/Daten/Data/X -- 2021/rawdata/NANONIS/X -- session_demo/2021-01-18 + right now ... + + ... SPECS Nanonis spectras are stored as thumbs ... + ... SPECS Nanonis images are stored as thumbs ... + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift + Channel not found: OC_M1_Freq._Shift diff --git a/Utilities/Linux/Ubuntu_unity/AFM_thumbs.desktop b/Utilities/Linux/Ubuntu_unity/AFM_thumbs.desktop new file mode 100755 index 0000000..25764a3 --- /dev/null +++ b/Utilities/Linux/Ubuntu_unity/AFM_thumbs.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Application +Terminal=true +Name=AFM_thumbs +Icon=/home//bin/AFM_thumbs/AFM_thumbs_icon.png +Exec=/usr/bin/python /home//bin/AFM_thumbs/AFM_thumbs.py + diff --git a/Utilities/Windows/AFM_thumbs_icon.ico b/Utilities/Windows/AFM_thumbs_icon.ico new file mode 100755 index 0000000000000000000000000000000000000000..9990cb92f9f753488b27f830963d314db5a01831 GIT binary patch literal 370070 zcmeEv2Vh*)v9@djfdmq|=_Uy+jXw_vgia{QOG5I}8`Zt{-g}X|F&NvpS5>Q9y;`!> zd+)tiwq%=t{5gN?;(}l5e_8`t16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G16l)G z16l)G16l)G15Rn+wmZH(Xz-o)KYzzvL;j>i>%fV7;Lo^kUcBwj`v*C7!|5mYDGdz1 zYsj^bFbHYUI&ktHh{p4;>r*$hz8I%8fc3M%|E+`Xp_^~NTgw;J!7cc^-WFcN+wZ*Z za_r|C|4yN;?>*TX|Mv`efPVekKhVh0<7mXFv0A=}4n~fl;VdJ@(6AAsr3@cULx+zN z^6s#aWRaox8uHG&BP{YZzJB}N;q=x!EW@O{J&fLbdnmp6mXtT%dY9gK^IiIfkay_s zZ?L>g|A74cA8&vDo8SJS`p1ty6?WIX-*LnG9_c|jjMs{R{2Rjii^hN7gS1mugf$fW z&wTN~!#|)SN8PEpxtW@pnzT5ngT}^2YG`Pn`ucjRtE;2h+FGiqsio@bYO1QL5>io7 zK`iCvo@MY^S&OD zyYIa3y1{qd|0motts4JM!K}|d*%tplB=2Ls^y#Oc(#Icvti=f(T)1$7&YwRoq_wq` zSk9h3D}?t`meZ$CQ&VFTiG8Bp(LPawJ))W_E32?aRAP^)wAmwge_-MLp|GIH*dGe8 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 +md "%progdir%" 2>nul + +::temporäres VBScript erzeugen ... + >%temp%\MakeShortCut.vbs echo Set objShell=WScript.CreateObject("Wscript.Shell") +>>%temp%\MakeShortCut.vbs echo Set objShortcut=objShell.CreateShortcut("%zielpfad%\%progtitel%.lnk") +>>%temp%\MakeShortCut.vbs echo objShortcut.TargetPath="%progdir%\%progexe%" +>>%temp%\MakeShortCut.vbs echo objShortcut.Description="%beschreibung%" +>>%temp%\MakeShortCut.vbs echo objShortcut.WorkingDirectory="%progdir%" +>>%temp%\MakeShortCut.vbs echo objShortcut.IconLocation = "C:\Users\Niklas\Documents\Python Scripts\AFM_thumbs_v1.7x_04.10.14\AFM_thumbs Icon.ico" +>>%temp%\MakeShortCut.vbs echo objShortcut.Save + +::... ausführen ... +cscript //nologo %temp%\MakeShortCut.vbs + +::... und wieder löschen. +del %temp%\MakeShortCut.vbs \ No newline at end of file diff --git a/Utilities/Windows/Windows_batch_starter.bat b/Utilities/Windows/Windows_batch_starter.bat new file mode 100755 index 0000000..490cbed --- /dev/null +++ b/Utilities/Windows/Windows_batch_starter.bat @@ -0,0 +1,3 @@ +@echo off + +cmd /C "python AFM_thumbs.py" \ No newline at end of file