commit 6b9d1f4a61172369d5bbb679dc43c9e176105ee4 Author: Clemens Barth Date: Fri Apr 8 17:39:57 2022 +0200 First committing 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 0000000..a9bb2b1 Binary files /dev/null and b/AFM_thumbs.pyc differ 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 0000000..662a2d7 Binary files /dev/null and b/AFM_thumbs/Channel.pyc differ 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 0000000..f58aad7 Binary files /dev/null and b/AFM_thumbs/Colour.pyc differ diff --git a/AFM_thumbs/Command_line.py b/AFM_thumbs/Command_line.py new file mode 100755 index 0000000..40804ac --- /dev/null +++ b/AFM_thumbs/Command_line.py @@ -0,0 +1,308 @@ +# ##### 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 matplotlib +from optparse import OptionParser + +from AFM_thumbs.Variables import RHK_special +from AFM_thumbs.Variables import globvar_fonts +from AFM_thumbs.Variables import globvar_bad_fonts +from AFM_thumbs.Variables import globvar_ThumbPara +from AFM_thumbs.Variables import globvar_AFMdir +from AFM_thumbs.Variables import globvar_thumb_size_x +from AFM_thumbs.Variables import globvar_thumb_size_y +from AFM_thumbs.Variables import globvar_spaces +from AFM_thumbs.Initialize import initialize_check_config +from AFM_thumbs.Channel import define_color + + +def command_line(): + + print("\n\n") + + parser = OptionParser(usage="usage: %prog [options]", version="%prog 1.6") + + parser.add_option("-d", "--directory", + action="store", + type="string", + dest="directory", + help="the working directory, from which all other " \ + "sub-directories are eventually considered " \ + "(see config file of AFM_thumb).") + + parser.add_option("-c", "--configfile", + action="store", + type="string", + dest="configfile", + help="the file path of the config file." \ + " - This option only acts if the " \ + "-d option is choosen.") + + parser.add_option("-p", "--pdf", + action="store", + dest="pdf", + help="the path of the directory, in which the " \ + "PDF files shall be stored into." \ + " - This option only acts if the " \ + "-d option is choosen.") + + + (options, args) = parser.parse_args() + + # If the working directory (-d option) is set => 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 0000000..f60073c Binary files /dev/null and b/AFM_thumbs/Command_line.pyc differ 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 0000000..fdea305 Binary files /dev/null and b/AFM_thumbs/Initialize.pyc differ 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 0000000..957e093 Binary files /dev/null and b/AFM_thumbs/Linalg.pyc differ 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 0000000..1b55f89 Binary files /dev/null and b/AFM_thumbs/Nanotec_DULCINEA.pyc differ 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 0000000..22b452d Binary files /dev/null and b/AFM_thumbs/Omicron_SCALA.pyc differ 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 0000000..013423f Binary files /dev/null and b/AFM_thumbs/PDF.pyc differ 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 0000000..f2de915 Binary files /dev/null and b/AFM_thumbs/RHK.pyc differ 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 0000000..3da3210 Binary files /dev/null and b/AFM_thumbs/SPECS_Nanonis.pyc differ diff --git a/AFM_thumbs/SPECS_Nanonis.txt b/AFM_thumbs/SPECS_Nanonis.txt new file mode 100755 index 0000000..5bf57cf --- /dev/null +++ b/AFM_thumbs/SPECS_Nanonis.txt @@ -0,0 +1,571 @@ +# ##### 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 !!! +# + +# Example for the complete header of a SPECS Nanonis '.sxm' file +# ============================================================== +# +# :NANONIS_VERSION: +# 2 +# :SCANIT_TYPE: +# FLOAT MSBFIRST +# :REC_DATE: +# 17.01.2021 +# :REC_TIME: +# 11:22:04 +# :REC_TEMP: +# 290.0000000000 +# :ACQ_TIME: +# 32.8 +# :SCAN_PIXELS: +# 256 256 +# :SCAN_FILE: +# D:\Session_test\Session_first_time_test\Test0001.sxm +# :SCAN_TIME: +# 6.400E-2 6.400E-2 +# :SCAN_RANGE: +# 2.000000E-8 2.000000E-8 +# :SCAN_OFFSET: +# 0.000000E+0 0.000000E+0 +# :SCAN_ANGLE: +# 0.000E+0 +# :SCAN_DIR: +# up +# :BIAS: +# 2.000E+0 +# :Z-CONTROLLER: +# Name on Setpoint P-gain I-gain T-const +# log Current 1 5.000E-11 A 2.000E-10 m 2.000E-7 m/s 1.000E-3 s +# :COMMENT: +# Aha, so geht das ... +# :NanonisMain>Session 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 0000000..bb42cbd Binary files /dev/null and b/AFM_thumbs/Thumbs.pyc differ diff --git a/AFM_thumbs/ToolTip.py b/AFM_thumbs/ToolTip.py new file mode 100755 index 0000000..8d302e4 --- /dev/null +++ b/AFM_thumbs/ToolTip.py @@ -0,0 +1,77 @@ +# ##### 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 !!! +# + +# This class implements Tooltips for Tkinter +# Original source: http://www.voidspace.org.uk/python/weblog/arch_d7_2006_07_01.shtml + +from tkinter import * + +class ToolTip(object): + + def __init__(self, widget): + self.widget = widget + self.tipwindow = None + self.id = None + self.x = self.y = 0 + + def showtip(self, text): + "Display text in tooltip window" + self.text = text + if self.tipwindow or not self.text: + return + x, y, cx, cy = self.widget.bbox("insert") + x = x + self.widget.winfo_rootx() + 27 + y = y + cy + self.widget.winfo_rooty() +27 + self.tipwindow = tw = Toplevel(self.widget) + tw.wm_overrideredirect(1) + tw.wm_geometry("+%d+%d" % (x, y)) + try: + # For Mac OS + tw.tk.call("::tk::unsupported::MacWindowStyle", + "style", tw._w, + "help", "noActivates") + except TclError: + pass + label = Label(tw, text=self.text, justify=LEFT, + background="#ffffe0", relief=SOLID, borderwidth=1, + font=("tahoma", "8", "normal")) + label.pack(ipadx=1) + + def hidetip(self): + tw = self.tipwindow + self.tipwindow = None + if tw: + tw.destroy() + +def create_tool_tip(widget, text): + toolTip = ToolTip(widget) + def enter(event): + toolTip.showtip(text) + def leave(event): + toolTip.hidetip() + widget.bind('', enter) + widget.bind('', leave) + widget.bind('', leave) diff --git a/AFM_thumbs/ToolTip.pyc b/AFM_thumbs/ToolTip.pyc new file mode 100755 index 0000000..4fd8515 Binary files /dev/null and b/AFM_thumbs/ToolTip.pyc differ diff --git a/AFM_thumbs/Variables.py b/AFM_thumbs/Variables.py new file mode 100755 index 0000000..682c01d --- /dev/null +++ b/AFM_thumbs/Variables.py @@ -0,0 +1,648 @@ +# ##### 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 !!! +# + + +# +# +# __________ Change the name and path of the config file ___________ from here +# +# +# +globvar_configfile = "Config_AFM_thumbs.conf" +globvar_configfile_path = "./AFM_thumbs/" + +# Example for Linux +# globvar_configfile_path = "/home/user/bin/AFM_thumbs/" +# globvar_configfile = "Config_AFM_thumbs.conf" +# +# Example for Windows +# globvar_configfile_path = "C:\Users\Username\Desktop\AFmThumbnails\" \ +# "AFM_thumbs" +# globvar_configfile = "Config_AFM_thumbs.conf" + +# +# +# +# _____________________________________________________________________ to here +# +# +# + + + + + +# ____________________________________________________________ Global variables + +# DO NOT CHANGE ANYTHING BELOW, OTHERWISE YOU KNOW WHAT TO DO ! + +import time + +globvar_contributions = "Reinhard Olbrich (testing)\n" \ + "Matthias Temmen (testing)\n" \ + "Alexander v Schmidtsfeld (testing)\n" \ + "..." + +globvar_year = "2022-03-02" +globvar_version = "3.001" + +globvar_spaces = " " +globvar_name = "AFM thumbs v" + globvar_version +globvar_bar_title = (globvar_name + " - " + + globvar_year) +globvar_note = ("Version " + globvar_version + " (" + + globvar_year + ")\n" + "www.development.root-1.de\n\n" + + "Coordinated by:\n\n" + + "Clemens Barth\n" + + "(barth@root-1.de)\n\n" + + " and\n\n" + + "Niklas Rethmann " + + "(nrethmann@uni-osnabrueck.de)\n\n"+ + "Contributions from:\n" + + globvar_contributions) + +globvar_console = ("\n\n"+ + globvar_spaces + + globvar_name + " - " + + globvar_year + "\n" + + globvar_spaces + "www.root-1.de\n\n" + + globvar_spaces + "Today: " + + time.strftime("%d-%m-%Y") + + ", Time: " + + time.strftime("%H:%M:%S")) + +globvar_python_directory = "AFM_thumbs" +globvar_default_config = "Config_default.conf" + +globvar_thumb_size_x = 5.0 +globvar_thumb_size_y = 6.0 +globvar_thumb_text_width = 40 + +globvar_timepassed_1 = ("\n" + + globvar_spaces + + "Overall passed time: ") +globvar_timepassed_2 = "--- %d days --- %d hours --- %d minutes " + \ + "--- %0.3f seconds ---\n\n" + +# _______________________________________________________________ SPECS Nanonis + +SPECS_Nanonis_images_must_exist = ".sxm" +SPECS_Nanonis_spectroscopy_must_exist = ".dat" + +# _______________________________________________________________ Omicron SCALA + +Omicron_SCALA_must_exist = ".par" +Omicron_SCALA_forward = ".tf" +Omicron_SCALA_backward = ".tb" + +# ____________________________________________________________ Nanotec DULCINEA + +Nanotec_DULCINEA_must_exist = ".f.top" +Nanotec_DULCINEA_forward = ".f." +Nanotec_DULCINEA_backward = ".b." +Nanotec_DULCINEA_suffix = ["f.top","f.ch4","f.ch5","f.ch6","f.ch7","f.ch8", + "b.top","b.ch4","b.ch5","b.ch6","b.ch7","b.ch8", + ".f.1st.Auxfeed", ".f.2nd.Auxfeed", + ".b.1st.Auxfeed", ".b.2nd.Auxfeed"] + +# _________________________________________________________________________ RHK + +RHK_must_exist = [".SM4", ".sm4"] +RHK_all_directions = ["all", "All", "ALL", "A", "a"] +RHK_forward_direction = ["forward", "Forward", "FORWARD", "for", + "For", "FOR", "f", "F"] +RHK_backward_direction = ["backward", "Backward", "BACKWARD", + "back", "Back", "BACK", "b", "B"] + + +RHK_message_direction = " --- Some RHK files could be detected! ---\n\n" \ + "Choose scan direction: (f)orward" \ + ", (b)ackward, (a)ll: " +# ____________________________________________________________________ Tooltips + +# Arrangement +TT_n_col = "Number of images in a column \n\n\ +This option lets you specific how \n\ +many images have to be in a column \n\n" + +TT_n_row = "Number of images in arow \n\n\ +This option lets you specific how \n\ +many images have to be in a row \n\n" + +TT_rms = "Contrast (times rms value) \n\n\ +This option lets you specific the \n\ +contrast of the images" + +TT_res = "Image resolution factor (in percent) \n\n\ +This option lets you specific the \n\ +resolution of the images" + +TT_qual = "Image quality \n\n\ +This option lets you specific the \n\ +quality of the images" + +# Position +TT_size = "Font size \n\n\ +This option lets you specific the \n\ +font size of the image text" + +TT_dx_pos = "dX position (in percent) \n\n\ +This option lets you shift the \n\ +image text left or right" + +TT_dy_pos = "dY position (in percent) \n\n\ +This option lets you shift the \n\ +image text up or down" + +TT_dw = "dWidth of text (in characters) \n\n\ +This option lets you specific the \n\ +width of the image text." + +# Specification +TT_file_ex = "This option lets you specific which \n\ +format should be considered" + +TT_master_dir = "This option lets you specific which \n\ +folders should be considered. \n\ +Should only be used together with the \"All sub-directories\" option" + +TT_filename = "This option lets you specific which \n\ +files should be considered." + +# Param +TT_date = "Include date and time \n\ +in the image text" + +TT_size_nm = "Include size in nanometer \n\ +in the image text" + +TT_size_px = "Include size in pixel \n\ +in the image text" + +TT_off = "Include offset in nanometer \n\ +in the image text" + +TT_vol = "Includes voltage (Volt) \n\ +in the image text" + +TT_feed = "Includes feedback\n\ +in the image text" + +TT_loop = "Includes loop gain\n\ +in the image text" + +TT_speed = "Include acquisition speed in s/line \n\ +in the image text" + +TT_amp = "Include amplitude\n\ +in the image text" + +TT_angle = "Include angle in degree \n\ +in the image text" + +# Other +TT_thumb_before = "Delete thumbs before all \n\n\ +With this option enabled, the thumbnail directory \n\ +will be deleted before a pdf thumbnail is created." + +TT_thumb_after = "Delete thumbs after all \n\n\ +With this option enabled, the thumbnail directory \n\ +will be deleted after a pdf thumbnail has been created." + +TT_extra_dir = "Extra directory \n\n\ +Creates extra WSxM and Gwyddion directories. \n\ +Two new directories are created in the directory one level above.\n\ +The directory structure(s) of the AFM data is(are) conserved." + +TT_pdfs = "Replace existing pdfs \n\n\ +Existing pdf files are replaced by new ones." + +TT_subdirs = "All sub-directories \n\n\ +All subdirectories of the selected directory (Button 'Choose directory')\n\ +are also considered. The respective pdf files are placed into the\n\ +directory one level above." + +TT_png = "Create images in png format \n\n\ +Change the image format of the thumbnails from jpeg to png." + +TT_spektral = " Include spectras \n\n\ +With this option images of spectra are included\n\ +into the pdf file." + +TT_peek = " Set color scale to peek-peek \n\n\ +This option permits setting the color scale of the \n\ +images to peek-to-peek values." + +TT_minimum_on_zero = " Set minimum value on zero \n\n\ +This option permits setting the minimum value of \n\ +the images onto zero." + +TT_Reich = "Reichling Special Options \n\n\ +This option triggers the following features: \n\ + - Colour for Kelvin images is set to gray \n\ + - One df image is inverted" + +# _____________________________________________________________________ For all + +ID_topography = r"[Tt]op(ograph(y|ie))?|TOP(OGRAPH(Y|IE))?|[Zz]" +ID_amplitude = r"[Aa]mplitude|AMPLITUDE|[Aa]mpl?\.?|AMPL?\.?" +ID_kelvin = r"[Kk]el(vin)?|KEL(VIN)?" +ID_kelvin_err = r"[Ee]rr(or)?|ERR(OR)?|[Ll]1[Xx]|KELVIN_ERR" +ID_df = r"[Dd][Ff]" +ID_df_fil = r"[Ff]iltered|FILTERED" +ID_dissipation = r"[Dd](issipation)?|DISSIPATION|[Dd]amp|DAMP|[Pp][Ll][Ll]" +ID_excitation = r"[Ee]xcitation|EXCITATION" +ID_ext1 = r"[Ee]xt(ernal)?( )?1|[Ee]XT(ERNALl)?( )?1" +ID_ext2 = r"[Ee]xt(ernal)?( )?2|[Ee]XT(ERNALl)?( )?2" +ID_phase = r"[Pp]ha(se)?|PHA(SE)?" + +ID_list = [ID_topography, ID_amplitude, ID_kelvin, ID_kelvin_err, ID_df, + ID_df_fil, ID_dissipation, ID_excitation, ID_ext1, ID_ext2, + ID_phase] + +ID_abbreviations = {"Topography" : "Z", "filtered df":"df_fil", "Amplitude":"A", + "Dissipation": "D", "Kelvin Error": "KPFM_err", + "Ext 1": "Ext1", "Ext 2": "Ext2", "Excitation": "A_ext", + "Phase": "Phase", "Kelvin": "KPFM", "DF_DIG": "df", + "EXT": "Ext", "EXT1": "Ext1", "EXT2": "Ext2"} + +# ______________________________________________________________________ Colors + +# Colors: see http://matplotlib.org/examples/color/colormaps_reference.html +# Note that many other colours still exist, pre-defined! + +globvar_ttk_Combobox = 10 + +globvar_color_options = ["Grey", "Red", "Red2", "Blue", "Blue2", "Green", + "ReiGreen", "Yellow", "Gold", + "Orange", "Purples", + "BlueGreen", "GreenBlu", + "BluePurple", "PurpleBlue", "PupleRed", "RedPurple", + "OrangeRed", + "PurpleBlueGreen", + "Gnuplot", "Gnuplot2", "Ocean", "Rainbow", + "Gist_rainbow", "HSV", "Gist_stern", "Jet", + "Hot", "AFMhot", "Bone", "Gist_heat"] + +# This red is very nice and also ... +Color_Red = {'red': ((0.0, 0.0, 0.0), + (0.333, 0.6, 0.6), + (0.666, 1.0, 1.0), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +# ... this yellow, ... +Color_Yellow = {'red': ((0.0, 0.0, 0.0), + (0.333, 0.7, 0.7), + (0.666, 1.0, 1.0), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.333, 0.8, 0.8), + (0.666, 1.0, 1.0), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +# ... this blue, ... +Color_Blue = {'red': ((0.0, 0.0, 0.0), + (0.3, 0.0, 0.0), + (0.7, 0.9, 0.9), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.3, 0.0, 0.0), + (0.7, 0.9, 0.9), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.7, 0.9, 0.9), + (1.0, 1.0, 1.0))} + +# ... gold and of course ... +Color_Gold = {'red': ((0.0, 0.0, 0.0), + (0.333, 0.545098039216, 0.545098039216), + (0.666, 0.803921568627, 0.803921568627), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.333, 0.458823529412, 0.458823529412), + (0.666, 0.678431372549, 0.678431372549), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +# ... the famous green colour from the Michael Reichling group. +Color_ReiGreen = {'red': ((0.0, 0.0, 0.0), + (0.381166, 0.0, 0.0), + (0.672646, 0.471014, 0.471014), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.381166, 0.381166, 0.381166), + (0.672646, 0.672646, 0.672646), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.381166, 0.0, 0.0), + (0.672646, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +Color_list = ["Greys_r", "Reds_r", Color_Red, "Blues_r", Color_Blue, "Greens_r", + Color_ReiGreen, Color_Yellow, Color_Gold, + "Oranges_r", "Purples_r", + "BuGn_r", "GnBu_r", + "BuPu_r", "PuBu_r", "PuRd_r", "RdPu_r", + "OrRd_r", + "PuBuGn_r", + "gnuplot", "gnuplot2", "ocean", "rainbow", + "gist_rainbow", "hsv", "gist_stern", "jet", + "hot", "afmhot", "bone", "gist_heat"] + +globvar_color_dict = {name:color for name, color in \ + zip(globvar_color_options, Color_list)} + +# ___________________________________________________________________ Fonts + +globvar_fonts = ['Courier', 'Courier New', 'Arial', 'FreeSans'] + +globvar_bad_fonts = ['NotoColorEmoji.ttf'] + +# ___________________________________________________________________ Classes + +class CLASSparameters(object): + def __init__(self, row, col, rms, res, font, + thumbs_before, thumbs_after, peek, minimum_on_zero, + png, date, sizenm, + sizepx, offset, voltage, feedback, gain, + speed, ampl, text_block, text_block_height, + text_size, pdfs, text_x, text_y, angle, + extra_direct, extension, masterdir, filename, jpeg, + channel_names, thumbs, line_fit, plane_fit, invert, + colors, geometry_x, geometry_y, spektra): + self.row = row + self.col = col + self.rms = rms + self.res = res + self.font = font + self.thumbs_before = thumbs_before + self.thumbs_after = thumbs_after + self.peek = peek + self.minimum_on_zero = minimum_on_zero + self.png = png + self.date = date + self.sizenm = sizenm + self.sizepx = sizepx + self.offset = offset + self.voltage = voltage + self.feedback = feedback + self.gain = gain + self.speed = speed + self.ampl = ampl + self.text_block = text_block + self.text_block_height = text_block_height + self.text_size = text_size + self.pdfs = pdfs + self.text_x = text_x + self.text_y = text_y + self.angle = angle + self.extra_direct = extra_direct + self.extension = extension + self.masterdir = masterdir + self.filename = filename + self.jpeg = jpeg + self.channel_names = channel_names + self.thumbs = thumbs + self.line_fit = line_fit + self.plane_fit = plane_fit + self.invert = invert + self.colors = colors + self.geometry_x = geometry_x + self.geometry_y = geometry_y + self.spektra = spektra + +class CLASSdir(object): + def __init__(self, working_directory, pdf_path, + thumbnail_directory, data_directory_name): + self.working_directory = working_directory + self.pdf_path = pdf_path + self.thumbnail_directory = thumbnail_directory + self.data_directory_name = data_directory_name + + +class CLASSdata(object): + __slots__ = ('date', 'x_size', 'y_size', 'x_pixel', 'y_pixel', + 'x_off', 'y_off', + 'voltage', 'measurement_type', 'feedback', + 'gain', 'gain_prop', 'gain_int', 'gain_xy', + 'gain_signal', 'gain_z', + 'speed', 'amplitude', 'angle', 'scan_updown', + 'sweep_f0', 'sweep_phase', 'sweep_A_exec', 'sweep_Q', + 'NONE', + 'datfile', 'channel', 'unit', + 'z_average', 'z_calibration', 'z_factor', 'z_offset', 'z_min', + 'z_max', 'res_freq', 'z_amplitude', + 'scandir', 'spec_x_unit', 'spec_x_label', + 'spec_y_unit', 'spec_y_label', 'spec_y_factor', + 'spec_points', 'spec_feedback', 'spec_acquisition', + 'spec_delay', 'spec_time', 'spec_position', 'spec_files', + 'spec_other') + def __init__(self, + date, + x_size, + y_size, + x_pixel, + y_pixel, + x_off, + y_off, + voltage, + measurement_type, + feedback, + gain, + gain_prop, + gain_int, + gain_xy, + gain_signal, + gain_z, + speed, + res_freq, + amplitude, + angle, + scan_updown, + sweep_f0, + sweep_phase, + sweep_A_exec, + sweep_Q, + # + # From here to end: lists + # + NONE, + datfile, + channel, + unit, + z_average, + z_calibration, + z_factor, + z_offset, + z_min, + z_max, + z_amplitude, + scandir, + spec_x_unit, + spec_x_label, + spec_y_unit, + spec_y_label, + spec_y_factor, + spec_points, + spec_feedback, + spec_acquisition, + spec_delay, + spec_time, + spec_position, + spec_files, + spec_other): + self.date = date + self.x_size = x_size + self.y_size = y_size + self.x_pixel = x_pixel + self.y_pixel = y_pixel + self.x_off = x_off + self.y_off = y_off + self.voltage = voltage + self.measurement_type = measurement_type # SPECS Nanonis + self.feedback = feedback # I, df, etc. + self.gain = gain # SCALA + self.gain_prop = gain_prop # DULCINEA + self.gain_int = gain_int # DULCINEA + self.gain_xy = gain_xy # DULCINEA + self.gain_signal = gain_signal # DULCINEA + self.gain_z = gain_z # DULCINEA + self.speed = speed + self.res_freq = res_freq + self.amplitude = amplitude + self.angle = angle + self.scan_updown = scan_updown # SPECS Nanonis + self.sweep_f0 = sweep_f0 # SPECS Nanonis + self.sweep_phase = sweep_phase # SPECS Nanonis + self.sweep_A_exec = sweep_A_exec # SPECS Nanonis + self.sweep_Q = sweep_Q # SPECS Nanonis + self.NONE = NONE # This is a dummy ... + # + # From here to end: lists + # + self.datfile = datfile + self.channel = channel + self.unit = unit + self.z_average = z_average # float, is set during runtime + self.z_calibration = z_calibration + self.z_factor = z_factor # DULCINEA, not used + self.z_offset = z_offset # SPECS Nanonis + self.z_amplitude = z_amplitude + self.z_min = z_min # DULCINEA, not used + self.z_max = z_max # DULCINEA, not used + self.scandir = scandir + self.spec_x_unit = spec_x_unit + self.spec_x_label = spec_x_label + self.spec_y_unit = spec_y_unit + self.spec_y_label = spec_y_label + self.spec_y_factor = spec_y_factor + self.spec_points = spec_points + self.spec_feedback = spec_feedback + self.spec_acquisition = spec_acquisition + self.spec_delay = spec_delay + self.spec_time = spec_time + self.spec_position = spec_position + self.spec_files = spec_files + self.spec_other = spec_other # This can be used for any properties. + +class CLASSLinalg(object): + __slots__ = ('plane_M512', 'plane_M1024', + 'plane_x_vec512', 'plane_y_vec512', + 'plane_x_vec1024', 'plane_y_vec1024', + 'line_M512', 'line_M1024', + 'line_x_vec512', 'line_x_vec1024') + def __init__(self, plane_M512, plane_M1024, + plane_x_vec512, plane_y_vec512, + plane_x_vec1024, plane_y_vec1024, + line_M512, line_M1024, + line_x_vec512,line_x_vec1024): + self.plane_M512 = plane_M512 + self.plane_M1024 = plane_M1024 + self.plane_x_vec512 = plane_x_vec512 + self.plane_y_vec512 = plane_y_vec512 + self.plane_x_vec1024 = plane_x_vec1024 + self.plane_y_vec1024 = plane_y_vec1024 + self.line_M512 = line_M512 + self.line_M1024 = line_M1024 + self.line_x_vec512 = line_x_vec512 + self.line_x_vec1024 = line_x_vec1024 + + +# The next 2 classes are used specifically for the RHK routine. +class CLASSRHK_position_counter(object): + def __init__(self, position): + self.position = position + + def add(self): + self.position += 1 + +class CLASSRHK_direction_request(object): + def __init__(self, direction = all): + self.direction = direction + +class CLASSRHK_true(object): + def __init__(self, true = False): + self.true = true + +globvar_LINALG = CLASSLinalg(None,None,None,None,None,None,None,None,None,None) + +# The global variables 'globvar_AFMdata' and 'globvar_ThumbPara' are created! +globvar_AFMdata = CLASSdata(None,None,None,None,None,None,None,None,None,None, + None,None,None,None,None,None,None,None,None,None, + None,None,None,None,None,None, + [],[],[], None, [],[],[],[],[],[],[], + [],[],[],[],[],[],[],[], [], [], [], [], None) + +globvar_AFMdir = CLASSdir(None,None,None,None) + +globvar_ThumbPara = CLASSparameters(None, None, None, None, None, + False, False, False, False, False, False, + False, False, False, False, False, + False, False, False, + 0, 0, 0, False, 0, 0, False, + False, None, None, None, 0, + [], [], [], [], [], [], + [], [], None) + +# For RHK +RHK_PositionCounter = CLASSRHK_position_counter(None) +RHK_special = CLASSRHK_true(False) diff --git a/AFM_thumbs/Variables.pyc b/AFM_thumbs/Variables.pyc new file mode 100755 index 0000000..b07b566 Binary files /dev/null and b/AFM_thumbs/Variables.pyc differ diff --git a/AFM_thumbs/Variables.py~ b/AFM_thumbs/Variables.py~ new file mode 100755 index 0000000..216329f --- /dev/null +++ b/AFM_thumbs/Variables.py~ @@ -0,0 +1,568 @@ +# ##### 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 !!! +# + + +# +# +# __________ Change the name and path of the config file ___________ from here +# +# +# +globvar_configfile = "Config_AFM_thumbs.conf" +globvar_configfile_path = "./AFM_thumbs/" + +""" +Example for Linux +globvar_configfile_path = "/home/user/bin/AFM_thumbs/" +globvar_configfile = "Config_AFM_thumbs.conf" + +Example for Windows +globvar_configfile_path = "C:\Users\Username\Desktop\AFmThumbnails\" \ + "AFM_thumbs" +globvar_configfile = "Config_AFM_thumbs.conf" +""" +# +# +# +# _____________________________________________________________________ to here +# +# +# + + + + + +# ____________________________________________________________ Global variables + +# DO NOT CHANGE ANYTHING BELOW, OTHERWISE YOU KNOW WHAT TO DO ! + +import time + +globvar_year = "2016-01-15" +globvar_version = "2.2" + +globvar_spaces = " " +globvar_name = "AFM thumbs v" + globvar_version +globvar_bar_title = (globvar_name + " " + + globvar_year) +globvar_note = ("Coordinated by:\n\nClemens Barth\n" + + "(barth@root-1.de)\n\n" + + " and\n\n" + + "Niklas Rethmann (nrethmann@uni-osnabrueck.de)\n\n"+ + globvar_year + "\n\n" + "www.root-1.de") +globvar_console = ("\n\n"+ + globvar_spaces + + globvar_name + + "" + + globvar_year + "\n" + + globvar_spaces + "www.root-1.de\n" + + globvar_spaces + "Date: " + + time.strftime("%d-%m-%Y") + + ", Time: " + + time.strftime("%H:%M:%S")) + +globvar_python_directory = "AFM_thumbs" +globvar_default_config = "Config_default.conf" + +globvar_thumb_size_x = 5.0 +globvar_thumb_size_y = 5.0 +globvar_thumb_text_width = 50 + +globvar_timepassed_1 = ("\n" + + globvar_spaces + + "Overall passed time: ") +globvar_timepassed_2 = "--- %d days --- %d hours --- %d minutes " + \ + "--- %0.3f seconds ---\n\n" + +# _______________________________________________________________ Omicron SCALA + +Omicron_SCALA_must_exist = ".par" +Omicron_SCALA_forward = ".tf" +Omicron_SCALA_backward = ".tb" + +# ____________________________________________________________ Nanotec DULCINEA + +Nanotec_DULCINEA_must_exist = ".f.top" +Nanotec_DULCINEA_forward = ".f." +Nanotec_DULCINEA_backward = ".b." +Nanotec_DULCINEA_suffix = ["f.top","f.ch4","f.ch5","f.ch6","f.ch7","f.ch8", + "b.top","b.ch4","b.ch5","b.ch6","b.ch7","b.ch8", + ".f.1st.Auxfeed", ".f.2nd.Auxfeed", + ".b.1st.Auxfeed", ".b.2nd.Auxfeed"] + +# _________________________________________________________________________ RHK + +RHK_must_exist = [".SM4", ".sm4"] +RHK_all_directions = ["all", "All", "ALL", "A", "a"] +RHK_forward_direction = ["forward", "Forward", "FORWARD", "for", + "For", "FOR", "f", "F"] +RHK_backward_direction = ["backward", "Backward", "BACKWARD", + "back", "Back", "BACK", "b", "B"] + + +RHK_message_direction = " --- Some RHK files could be detected! ---\n\n" \ + "Choose scan direction: (f)orward" \ + ", (b)ackward, (a)ll: " +# ____________________________________________________________________ Tooltips + +# Arrangement +TT_n_col = "Number of images in a column \n\n\ +This option lets you specific how \n\ +many images have to be in a column \n\n" + +TT_n_row = "Number of images in arow \n\n\ +This option lets you specific how \n\ +many images have to be in a row \n\n" + +TT_rms = "Contrast (times rms value) \n\n\ +This option lets you specific the \n\ +contrast of the images" + +TT_res = "Image resolution factor (in percent) \n\n\ +This option lets you specific the \n\ +resolution of the images" + +TT_qual = "Image quality \n\n\ +This option lets you specific the \n\ +quality of the images" + +# Position +TT_size = "Font size \n\n\ +This option lets you specific the \n\ +font size of the image text" + +TT_dx_pos = "dX position (in percent) \n\n\ +This option lets you shift the \n\ +image text left or right" + +TT_dy_pos = "dY position (in percent) \n\n\ +This option lets you shift the \n\ +image text up or down" + +TT_dw = "dWidth of text (in characters) \n\n\ +This option lets you specific the \n\ +width of the image text." + +# Specification +TT_file_ex = "This option lets you specific which \n\ +format should be considered" + +TT_master_dir = "This option lets you specific which \n\ +folders should be considered. \n\ +Should only be used together with the \"All sub-directories\" option" + +TT_filename = "This option lets you specific which \n\ +files should be considered." + +# Param +TT_date = "Include date and time \n\ +in the image text" + +TT_size_nm = "Include size in nanometer \n\ +in the image text" + +TT_size_px = "Include size in pixel \n\ +in the image text" + +TT_off = "Include offset in nanometer \n\ +in the image text" + +TT_vol = "Includes voltage (Volt) \n\ +in the image text" + +TT_feed = "Includes feedback\n\ +in the image text" + +TT_loop = "Includes loop gain\n\ +in the image text" + +TT_speed = "Include acquisition speed in s/line \n\ +in the image text" + +TT_amp = "Include amplitude\n\ +in the image text" + +TT_angle = "Include angle in degree \n\ +in the image text" + +# Other +TT_thumb_before = "Delete thumbs before all \n\n\ +With this option enabled, the thumbnail directory \n\ +will be deleted before a pdf thumbnail is created." + +TT_thumb_after = "Delete thumbs after all \n\n\ +With this option enabled, the thumbnail directory \n\ +will be deleted after a pdf thumbnail has been created." + +TT_extra_dir = "Extra directory \n\n\ +Creates extra WSxM and Gwyddion directories. \n\ +Two new directories are created in the directory one level above.\n\ +The directory structure(s) of the AFM data is(are) conserved." + +TT_pdfs = "Replace existing pdfs \n\n\ +Existing pdf files are replaced by new ones." + +TT_subdirs = "All sub-directories \n\n\ +All subdirectories of the selected directory (Button 'Choose directory')\n\ +are also considered. The respective pdf files are placed into the\n\ +directory one level above." + +TT_png = "Create images in png format \n\n\ +Change the image format of the thumbnails from jpeg to png." + +TT_spektral = " Include spectras \n\n\ +With this option images of spectra are included\n\ +into the pdf file." + +TT_peek = " Set color scale to peek-peek \n\n\ +This option permits setting the color scale of the \n\ +images to peek-to-peek values." + +TT_minimum_on_zero = " Set minimum value on zero \n\n\ +This option permits setting the minimum value of \n\ +the images onto zero." + +TT_Reich = "Reichling Special Options \n\n\ +This option triggers the following features: \n\ + - Colour for Kelvin images is set to gray \n\ + - One df image is inverted" + +# _____________________________________________________________________ For all + +ID_topography = r"[Tt]op(ograph(y|ie))?|TOP(OGRAPH(Y|IE))?|[Zz]" +ID_amplitude = r"[Aa]mplitude|AMPLITUDE|[Aa]mpl?\.?|AMPL?\.?" +ID_kelvin = r"[Kk]el(vin)?|KEL(VIN)?" +ID_kelvin_err = r"[Ee]rr(or)?|ERR(OR)?|[Ll]1[Xx]" +ID_df = r"[Dd][Ff]" +ID_df_fil = r"[Ff]iltered|FILTERED" +ID_dissipation = r"[Dd](issipation)?|DISSIPATION|[Dd]amp|DAMP|[Pp][Ll][Ll]" +ID_excitation = r"[Ee]xcitation|EXCITATION" +ID_ext1 = r"[Ee]xt(ernal)?( )?1|[Ee]XT(ERNALl)?( )?1" +ID_ext2 = r"[Ee]xt(ernal)?( )?2|[Ee]XT(ERNALl)?( )?2" +ID_phase = r"[Pp]ha(se)?|PHA(SE)?" + +ID_list = [ID_topography, ID_amplitude, ID_kelvin, ID_kelvin_err, ID_df, + ID_df_fil, ID_dissipation, ID_excitation, ID_ext1, ID_ext2, ID_phase] + +ID_abbreviations = {"Topography" : "Z", "filtered df":"df_fil", "Amplitude":"A", + "Dissipation": "D", "Kelvin Error": "KPFM_err", + "Ext 1": "Ext1", "Ext 2": "Ext2", "Excitation": "A_ext", + "Phase": "Phase", "Kelvin": "KPFM", "DF_DIG": "df", + "EXT": "Ext", "EXT1": "Ext1", "EXT2": "Ext2"} + +# ______________________________________________________________________ Colors + +# Colors: see http://matplotlib.org/examples/color/colormaps_reference.html +# Note that many other colours still exist, pre-defined! + +globvar_ttk_Combobox = 10 + +globvar_color_options = ["Grey", "Red", "Red2", "Blue", "Blue2", "Green", + "ReiGreen", "Yellow", "Gold", + "Orange", "Purples", + "BlueGreen", "GreenBlu", + "BluePurple", "PurpleBlue", "PupleRed", "RedPurple", + "OrangeRed", + "PurpleBlueGreen", + "Gnuplot", "Gnuplot2", "Ocean", "Rainbow", + "Gist_rainbow", "HSV", "Gist_stern", "Jet", + "Hot", "AFMhot", "Bone", "Gist_heat"] + +# This red is very nice and also ... +Color_Red = {'red': ((0.0, 0.0, 0.0), + (0.333, 0.6, 0.6), + (0.666, 1.0, 1.0), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +# ... this yellow, ... +Color_Yellow = {'red': ((0.0, 0.0, 0.0), + (0.333, 0.7, 0.7), + (0.666, 1.0, 1.0), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.333, 0.8, 0.8), + (0.666, 1.0, 1.0), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +# ... this blue, ... +Color_Blue = {'red': ((0.0, 0.0, 0.0), + (0.3, 0.0, 0.0), + (0.7, 0.9, 0.9), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.3, 0.0, 0.0), + (0.7, 0.9, 0.9), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.7, 0.9, 0.9), + (1.0, 1.0, 1.0))} + +# ... gold and of course ... +Color_Gold = {'red': ((0.0, 0.0, 0.0), + (0.333, 0.545098039216, 0.545098039216), + (0.666, 0.803921568627, 0.803921568627), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.333, 0.458823529412, 0.458823529412), + (0.666, 0.678431372549, 0.678431372549), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.333, 0.0, 0.0), + (0.666, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +# ... the green colour from the Michael Reichling group. +Color_ReiGreen = {'red': ((0.0, 0.0, 0.0), + (0.381166, 0.0, 0.0), + (0.672646, 0.471014, 0.471014), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.381166, 0.381166, 0.381166), + (0.672646, 0.672646, 0.672646), + (1.0, 1.0, 1.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.381166, 0.0, 0.0), + (0.672646, 0.0, 0.0), + (1.0, 1.0, 1.0))} + +Color_list = ["Greys_r", "Reds_r", Color_Red, "Blues_r", Color_Blue, "Greens_r", + Color_ReiGreen, Color_Yellow, Color_Gold, + "Oranges_r", "Purples_r", + "BuGn_r", "GnBu_r", + "BuPu_r", "PuBu_r", "PuRd_r", "RdPu_r", + "OrRd_r", + "PuBuGn_r", + "gnuplot", "gnuplot2", "ocean", "rainbow", + "gist_rainbow", "hsv", "gist_stern", "jet", + "hot", "afmhot", "bone", "gist_heat"] + +globvar_color_dict = {name:color for name, color in \ + zip(globvar_color_options, Color_list)} + +# ___________________________________________________________________ Fonts + +globvar_fonts = ['Courier', 'Courier New', 'Arial', 'FreeSans'] +# ___________________________________________________________________ Classes + +class CLASSparameters(object): + def __init__(self, row, col, rms, res, font, + thumbs_before, thumbs_after, peek, minimum_on_zero, + png, date, sizenm, + sizepx, offset, voltage, feedback, gain, + speed, ampl, text_block, text_block_height, + text_size, pdfs, text_x, text_y, angle, + extra_direct, extension, masterdir, filename, jpeg, + channel_names, thumbs, line_fit, plane_fit, invert, + colors, geometry_x, geometry_y, spektra): + self.row = row + self.col = col + self.rms = rms + self.res = res + self.font = font + self.thumbs_before = thumbs_before + self.thumbs_after = thumbs_after + self.peek = peek + self.minimum_on_zero = minimum_on_zero + self.png = png + self.date = date + self.sizenm = sizenm + self.sizepx = sizepx + self.offset = offset + self.voltage = voltage + self.feedback = feedback + self.gain = gain + self.speed = speed + self.ampl = ampl + self.text_block = text_block + self.text_block_height = text_block_height + self.text_size = text_size + self.pdfs = pdfs + self.text_x = text_x + self.text_y = text_y + self.angle = angle + self.extra_direct = extra_direct + self.extension = extension + self.masterdir = masterdir + self.filename = filename + self.jpeg = jpeg + self.channel_names = channel_names + self.thumbs = thumbs + self.line_fit = line_fit + self.plane_fit = plane_fit + self.invert = invert + self.colors = colors + self.geometry_x = geometry_x + self.geometry_y = geometry_y + self.spektra = spektra + +class CLASSdir(object): + def __init__(self, working_directory, pdf_path, + thumbnail_directory, data_directory_name): + self.working_directory = working_directory + self.pdf_path = pdf_path + self.thumbnail_directory = thumbnail_directory + self.data_directory_name = data_directory_name + + +class CLASSdata(object): + __slots__ = ('date', 'x_size', 'y_size', 'x_pixel', 'y_pixel', + 'x_off', 'y_off', + 'voltage', 'feedback', + 'gain', 'gain_prop', 'gain_int', 'gain_xy', + 'gain_signal', 'gain_z', + 'speed', 'amplitude', 'angle', 'NONE', + 'datfile', 'channel', 'unit', + 'z_average', 'z_calibration', 'z_factor', 'z_min', + 'z_max', 'z_amplitude', + 'scandir', 'spec_x_unit', 'spec_x_label', + 'spec_y_unit', 'spec_y_label', 'spec_y_factor', + 'spec_points', 'spec_feedback', 'spec_acquisition', + 'spec_delay') + def __init__(self, date, x_size, y_size, x_pixel, y_pixel, x_off, y_off, + voltage, feedback, + gain, gain_prop, gain_int, gain_xy, gain_signal, gain_z, + speed, amplitude, angle, NONE, + datfile, channel, unit, + z_average, z_calibration, z_factor, z_min, z_max, z_amplitude, + scandir, spec_x_unit, spec_x_label, + spec_y_unit, spec_y_label, spec_y_factor, + spec_points, spec_feedback, spec_acquisition, spec_delay): + self.date = date + self.x_size = x_size + self.y_size = y_size + self.x_pixel = x_pixel + self.y_pixel = y_pixel + self.x_off = x_off + self.y_off = y_off + self.voltage = voltage + self.feedback = feedback + self.gain = gain # SCALA + self.gain_prop = gain_prop # DULCINEA + self.gain_int = gain_int # DULCINEA + self.gain_xy = gain_xy # DULCINEA + self.gain_signal = gain_signal # DULCINEA + self.gain_z = gain_z # DULCINEA + self.speed = speed + self.amplitude = amplitude + self.angle = angle + self.NONE = NONE # This is a dummy ... + # From here to end: lists + self.datfile = datfile + self.channel = channel + self.unit = unit + self.z_average = z_average # float, is determined during runtime + self.z_calibration = z_calibration + self.z_factor = z_factor # DULCINEA, not used so far + self.z_amplitude = z_amplitude + self.z_min = z_min # DULCINEA, not used so far + self.z_max = z_max # DULCINEA, not used so far + self.scandir = scandir + self.spec_x_unit = spec_x_unit + self.spec_x_label = spec_x_label + self.spec_y_unit = spec_y_unit + self.spec_y_label = spec_y_label + self.spec_y_factor = spec_y_factor + self.spec_points = spec_points + self.spec_feedback = spec_feedback + self.spec_acquisition = spec_acquisition + self.spec_delay = spec_delay + + +class CLASSLinalg(object): + __slots__ = ('plane_M512', 'plane_M1024', + 'plane_x_vec512', 'plane_y_vec512', + 'plane_x_vec1024', 'plane_y_vec1024', + 'line_M512', 'line_M1024', + 'line_x_vec512', 'line_x_vec1024') + def __init__(self, plane_M512, plane_M1024, + plane_x_vec512, plane_y_vec512, + plane_x_vec1024, plane_y_vec1024, + line_M512, line_M1024, + line_x_vec512,line_x_vec1024): + self.plane_M512 = plane_M512 + self.plane_M1024 = plane_M1024 + self.plane_x_vec512 = plane_x_vec512 + self.plane_y_vec512 = plane_y_vec512 + self.plane_x_vec1024 = plane_x_vec1024 + self.plane_y_vec1024 = plane_y_vec1024 + self.line_M512 = line_M512 + self.line_M1024 = line_M1024 + self.line_x_vec512 = line_x_vec512 + self.line_x_vec1024 = line_x_vec1024 + + +# The next 2 classes are used specifically for the RHK routine. +class CLASSRHK_position_counter(object): + def __init__(self, position): + self.position = position + + def add(self): + self.position += 1 + +class CLASSRHK_direction_request(object): + def __init__(self, direction = all): + self.direction = direction + +class CLASSRHK_true(object): + def __init__(self, true = False): + self.true = true + + +globvar_LINALG = CLASSLinalg(None,None,None,None,None,None,None,None,None,None) + +globvar_AFMdata = CLASSdata(None,None,None,None,None,None,None,None,None,None, + None,None,None,None,None,None,None,None, None, + [],[],[], None, [],[],[],[],[],[],[], + [],[],[],[],[],[],[],[]) + +globvar_AFMdir = CLASSdir(None,None,None,None) + +globvar_ThumbPara = CLASSparameters(None, None, None, None, None, + False, False, False, False, False, False, + False, False, False, False, False, + False, False, False, + 0, 0, 0, False, 0, 0, False, + False, None, None, None, 0, + [], [], [], [], [], [], + [], [], None) + +# For RHK +RHK_PositionCounter = CLASSRHK_position_counter(None) +RHK_special = CLASSRHK_true(False) diff --git a/AFM_thumbs/__init__.py b/AFM_thumbs/__init__.py new file mode 100755 index 0000000..0b8f562 --- /dev/null +++ b/AFM_thumbs/__init__.py @@ -0,0 +1,25 @@ +# ##### 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 !!! +# diff --git a/AFM_thumbs/__init__.pyc b/AFM_thumbs/__init__.pyc new file mode 100755 index 0000000..b5e839e Binary files /dev/null and b/AFM_thumbs/__init__.pyc differ diff --git a/AFM_thumbs/__pycache__/Channel.cpython-36.pyc b/AFM_thumbs/__pycache__/Channel.cpython-36.pyc new file mode 100755 index 0000000..fc5e6ad Binary files /dev/null and b/AFM_thumbs/__pycache__/Channel.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/Channel.cpython-38.pyc b/AFM_thumbs/__pycache__/Channel.cpython-38.pyc new file mode 100644 index 0000000..b78e13b Binary files /dev/null and b/AFM_thumbs/__pycache__/Channel.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/Colour.cpython-36.pyc b/AFM_thumbs/__pycache__/Colour.cpython-36.pyc new file mode 100755 index 0000000..deee15f Binary files /dev/null and b/AFM_thumbs/__pycache__/Colour.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/Colour.cpython-38.pyc b/AFM_thumbs/__pycache__/Colour.cpython-38.pyc new file mode 100644 index 0000000..1cadcb9 Binary files /dev/null and b/AFM_thumbs/__pycache__/Colour.cpython-38.pyc differ 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 0000000..c39e501 Binary files /dev/null and b/AFM_thumbs/__pycache__/Command_line.cpython-36.pyc differ 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 0000000..845f3f2 Binary files /dev/null and b/AFM_thumbs/__pycache__/Command_line.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/Initialize.cpython-36.pyc b/AFM_thumbs/__pycache__/Initialize.cpython-36.pyc new file mode 100755 index 0000000..a34fd5f Binary files /dev/null and b/AFM_thumbs/__pycache__/Initialize.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/Initialize.cpython-38.pyc b/AFM_thumbs/__pycache__/Initialize.cpython-38.pyc new file mode 100644 index 0000000..293d572 Binary files /dev/null and b/AFM_thumbs/__pycache__/Initialize.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/Linalg.cpython-36.pyc b/AFM_thumbs/__pycache__/Linalg.cpython-36.pyc new file mode 100755 index 0000000..c82be48 Binary files /dev/null and b/AFM_thumbs/__pycache__/Linalg.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/Linalg.cpython-38.pyc b/AFM_thumbs/__pycache__/Linalg.cpython-38.pyc new file mode 100644 index 0000000..b2b7369 Binary files /dev/null and b/AFM_thumbs/__pycache__/Linalg.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-36.pyc b/AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-36.pyc new file mode 100755 index 0000000..8a64c7f Binary files /dev/null and b/AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-36.pyc differ 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 0000000..e239c57 Binary files /dev/null and b/AFM_thumbs/__pycache__/Nanotec_DULCINEA.cpython-38.pyc differ 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 0000000..9b1ff5c Binary files /dev/null and b/AFM_thumbs/__pycache__/Omicron_SCALA.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/Omicron_SCALA.cpython-38.pyc b/AFM_thumbs/__pycache__/Omicron_SCALA.cpython-38.pyc new file mode 100644 index 0000000..f2cbf2a Binary files /dev/null and b/AFM_thumbs/__pycache__/Omicron_SCALA.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/PDF.cpython-36.pyc b/AFM_thumbs/__pycache__/PDF.cpython-36.pyc new file mode 100755 index 0000000..93a3ea9 Binary files /dev/null and b/AFM_thumbs/__pycache__/PDF.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/PDF.cpython-38.pyc b/AFM_thumbs/__pycache__/PDF.cpython-38.pyc new file mode 100644 index 0000000..615cf0e Binary files /dev/null and b/AFM_thumbs/__pycache__/PDF.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/RHK.cpython-36.pyc b/AFM_thumbs/__pycache__/RHK.cpython-36.pyc new file mode 100755 index 0000000..fda7e02 Binary files /dev/null and b/AFM_thumbs/__pycache__/RHK.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/RHK.cpython-38.pyc b/AFM_thumbs/__pycache__/RHK.cpython-38.pyc new file mode 100644 index 0000000..b43c4be Binary files /dev/null and b/AFM_thumbs/__pycache__/RHK.cpython-38.pyc differ 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 0000000..3d07b78 Binary files /dev/null and b/AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-36.pyc differ 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 0000000..ac5ba76 Binary files /dev/null and b/AFM_thumbs/__pycache__/SPECS_Nanonis.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/Thumbs.cpython-36.pyc b/AFM_thumbs/__pycache__/Thumbs.cpython-36.pyc new file mode 100755 index 0000000..da17cc3 Binary files /dev/null and b/AFM_thumbs/__pycache__/Thumbs.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/Thumbs.cpython-38.pyc b/AFM_thumbs/__pycache__/Thumbs.cpython-38.pyc new file mode 100644 index 0000000..394a2d1 Binary files /dev/null and b/AFM_thumbs/__pycache__/Thumbs.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/ToolTip.cpython-36.pyc b/AFM_thumbs/__pycache__/ToolTip.cpython-36.pyc new file mode 100755 index 0000000..e881ebd Binary files /dev/null and b/AFM_thumbs/__pycache__/ToolTip.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/ToolTip.cpython-38.pyc b/AFM_thumbs/__pycache__/ToolTip.cpython-38.pyc new file mode 100644 index 0000000..fd213a5 Binary files /dev/null and b/AFM_thumbs/__pycache__/ToolTip.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/Variables.cpython-36.pyc b/AFM_thumbs/__pycache__/Variables.cpython-36.pyc new file mode 100755 index 0000000..a60a254 Binary files /dev/null and b/AFM_thumbs/__pycache__/Variables.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/Variables.cpython-38.pyc b/AFM_thumbs/__pycache__/Variables.cpython-38.pyc new file mode 100644 index 0000000..193992b Binary files /dev/null and b/AFM_thumbs/__pycache__/Variables.cpython-38.pyc differ diff --git a/AFM_thumbs/__pycache__/__init__.cpython-36.pyc b/AFM_thumbs/__pycache__/__init__.cpython-36.pyc new file mode 100755 index 0000000..53b0cd3 Binary files /dev/null and b/AFM_thumbs/__pycache__/__init__.cpython-36.pyc differ diff --git a/AFM_thumbs/__pycache__/__init__.cpython-38.pyc b/AFM_thumbs/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..333f144 Binary files /dev/null and b/AFM_thumbs/__pycache__/__init__.cpython-38.pyc differ diff --git a/AFM_thumbs_Icon.png b/AFM_thumbs_Icon.png new file mode 100755 index 0000000..e332446 Binary files /dev/null and b/AFM_thumbs_Icon.png differ diff --git a/Config_AFM_thumbs_noline.log b/Config_AFM_thumbs_noline.log new file mode 100755 index 0000000..90607ad --- /dev/null +++ b/Config_AFM_thumbs_noline.log @@ -0,0 +1,48 @@ + + + AFM thumbs v2.4 - 2021-02-05 + www.root-1.de + + Today: 05-02-2021, Time: 14:36:10 + + + + Attention: The config file + ./Config_AFM_thumbs_noline.conf + does not exist! + The default config file 'AFM_thumbs/Config_default.conf' is now used! + If you have your own config file, put in the correct file name and path + in 'AFM_thumbs/Variables.py' => '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 0000000..9990cb9 Binary files /dev/null and b/Utilities/Windows/AFM_thumbs_icon.ico differ diff --git a/Utilities/Windows/AFM_thumbs_starter.lnk b/Utilities/Windows/AFM_thumbs_starter.lnk new file mode 100755 index 0000000..1587475 Binary files /dev/null and b/Utilities/Windows/AFM_thumbs_starter.lnk differ diff --git a/Utilities/Windows/Create_Windows_shortcut.bat b/Utilities/Windows/Create_Windows_shortcut.bat new file mode 100755 index 0000000..da17dba --- /dev/null +++ b/Utilities/Windows/Create_Windows_shortcut.bat @@ -0,0 +1,35 @@ +@echo off & setlocal + +:: Source: http://www.administrator.de/forum/verkn%C3%BCpfung-auf-desktop-per-batch-anlegen-155061.html + +:: Zielpfad +set "zielpfad=%userprofile%\Desktop" + +::Name der Verknüpfung (ohne ".lnk") +set "progtitel=AFM_thumbs Starter" +::Speicherort der Programmdatei (wird auch für "Ausführen in:" verwendet) +set "progdir=%cd%" +set "progexe=Windows Batch Starter.bat" +::Kommentar +set "beschreibung=Run AFM_thumbs.py" +::Icon +set "iconpath=%progdir%\AFM_thumbs Icon.ico" + +::Bei Bedarf Ordner erstellen: +md "%zielpfad%" 2>nul +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