Warning: Python scripting is described in the user guide.
This is the old pygwy tutorial, currently preserved for reference. Many things written here do not represent the best practice and may be excessively unpythonic, convoluted or inefficient.
Some things written here are plain wrong and do not work.
Pygwy is a Python binding to Gwyddion's objects, methods and functions. It is suitable for writing modules (process and import/export) and simplifying repetitive or complex tasks. This document contains described examples of Pygwy usage.
The main reference of pygwy module is generated from Gwyddion documentation. Although I tried to catch main differences between C and Pygwy documentation, there is still a lot of inaccuracy.
Data processing module is used for manipulation with datafield (an "image"). It may compute some statistic values or alter datafield itself. The processing module is located in an application menu Data Process. Modules can be written in C or Python language. This sectionl covers a creation of data processing module in Python. For creating modules in C please refer to the module tutorial.
Variables plugin_type
and plugin_menu
must be defined
at the beginning of a process module file. They are metadata used for
determining module type and location in the application menu. For the data
processing module the values are following:
plugin_type = "PROCESS" plugin_menu= "/path/to/required/(sub)menu"
Then a run function follows. This function is executed everytime the module is invoked from application menu.
def run(): # main body of module function
Although it has no arguments there is predefined global variable (gwy.data) which contains an active container object. The container may hold a scale of values from object (for example datafields) to strings and numbers. However using the gwy.data variable is not always required.
Following example shows how to create a simple process module which inverts values in active datafield.
# This is required for usage of pygwy functions import gwy plugin_menu = "/Correct Data/Invert" plugin_type = "PROCESS" def run(): # Create undo point, the detailed explanation of this step is beyond this # tutorial. Basically the active container and datafield key are used for # storing information to undo stack. key = gwy.gwy_app_data_browser_get_current(gwy.APP_DATA_FIELD_KEY) gwy.gwy_app_undo_qcheckpointv(gwy.data, key) # Get active datafield and store it to 'd' variable. The variable is object # of type gwy.DataField d = gwy.gwy_app_data_browser_get_current(gwy.APP_DATA_FIELD) # Call invert function (do not invert x and y axes, invert only z axis) d.invert(0, 0, 1) # Report data change to Gwyddion, this is required to update (redraw) # graphical presentation of datafield in application window. d.data_changed()
Volume data processing modules are very similar to image data processing
modules. They declare plugin_type
as VOLUME
and
they will appear in the Volume toolbox menu:
plugin_type = "VOLUME" plugin_menu= "/path/to/required/(sub)menu" def run(): # main body of module function
File module is used to import and export data.
Variables plugin_type
and plugin_desc
must be defined
at the beginning of a import/export module file. They are metadata used for
determining module type and description of file format. For the import/export
module the values are following:
plugin_type = "FILE" plugin_desc = "Description of file format (.extension)"Complete module implements following functions:
detect_by_name(filename)
filename : |
A string containing full path to file. |
Returns: | A score <0,100> where value 0 reflects unknown type, value 100 reflects known type |
detect_by_content(filename, head, tail, filesize)
filename : |
A string containing full path to file |
head : |
A string containing few bytes from beginning of the file |
tail : |
A string containing few bytes from end of the file |
filesize : |
A length of file in bytes |
Returns: | A score <0,100> where value 0 reflects unknown type, value 100 reflects known type |
load(filename, mode=None)
filename : |
A string containing full path to file |
mode : |
The run mode, either gwy.RUN_INTERACTIVE or gwy.RUN_NONINTERACTIVE. |
Returns: | a new container of imported data. |
save(data, filename, mode=None)
data : |
A container of data used for export |
filename : |
A string containing full path to output file |
mode : |
The run mode, either gwy.RUN_INTERACTIVE or gwy.RUN_NONINTERACTIVE. |
Returns: | True when export is successful, False otherwise. |
Note: the mode parameter for load() and save() is available since version 2.26. To maintain backward compatibility with earlier versions, include the default value None in the function definitions. Scripts written for version 2.25 and earlier that do not define the mode parameter are still supported by version 2.26 and later.
import gwy, sys plugin_type = "FILE" plugin_desc = "High definition stable format store (.hdsf)" def detect_by_name(filename): if (filename.endswith(".hdsf")): return 100 else: return 0 def detect_by_content(filename, head, tail, filesize): if (head.startswith("HDSF:")): return 100 else: return 0 def load(filename, mode=None): c = gwy.Container() d = gwy.DataField(100, 100, 100, 100, 1) for i in range(100): for j in range(100): d.set_val(i, j, i) # draws linear gradient c.set_object_by_name("/0/data", d) return c def save(data, filename, mode=None): f = open(filename, "w") datafield_num = 1 for key in data.keys(): if isinstance(data.get_object(key), gwy.DataField): d = data.get_object(key) f.write("Datafield "+ str(datafield_num) + '\n') datafield_num += 1 for row in range(d.get_yres()): for col in range(d.get_xres()): f.write(str(d.get_val(col, row))+'\n') f.close() return True
Pygwy console is special module suitable for batch tasks inside of Gwyddion. It has no predefined variables (like gwy.data in processing module) but it still can control Gwyddion and it is more flexible. The console can be invoked from Data process menu (Data process/Pygwy console) (but some file must be opened before because console is technically process module).
The console looks like simplified text editor. It has main toolbar which serve for basic operation with files (open, save, save as and execute). Below is located editor which contains user-written code. On the bottom of window is textview with output and at the very bottom there is single input line. The console accepts some keyboard shortcuts for more productivity:
Following section contains examples for Pygwy console.
Create new datafield with semisphere from active datafield and append it to active file.
# semisphere radius radius = 100.0 # position in datafield resolution x0 = 100 y0 = 100 z0 = -30 # scaling factor factor = 10e-12 # get active datafield d = gwy.gwy_app_data_browser_get_current(gwy.APP_DATA_FIELD) # create new datafield by using active datafield and # set its values to zero sphere_datafield = d.new_alike(True) for y in range(d.get_yres()): for x in range(d.get_xres()): z = pow(radius, 2) - pow(x - x0, 2) - pow(y - y0, 2) if (z > 0): # set datafield's value sphere_datafield.set_val(x, y, (z-z0)*factor) # get active container c = gwy.gwy_app_data_browser_get_current(gwy.APP_CONTAINER) # add sphere datafield to active container gwy.gwy_app_data_browser_add_data_field(sphere_datafield, c, 3)
Compute root mean square (RMS) of specified number of iteration and step of gauss filter and store them to file.
# Gauss filter size size = 1.0 number_of_iteration = 21 # get current datafield d = gwy.gwy_app_data_browser_get_current(gwy.APP_DATA_FIELD) # filename for storing statistical values filename = "gaussian_filter_stats.txt" f = open(filename, "w") for i in range(number_of_iteration): # create copy of original datafield to_filter = d.duplicate() # apply gaussian filter to copy of datafield to_filter.filter_gaussian(i*size) # collect RMS to file f.write("iteration %d rms %e\n" % (i, to_filter.get_rms())) # get histogram histogram = gwy.DataLine(1, 1, False) to_filter.dh(histogram, -1) # write histogram to file f.write("histogram: ") for v in histogram.get_data(): f.write("%e \n" % v) f.write("\n" ) f.close()
Modify datafield by calling modules level and remove scars. Change datafield palette, export to PNG and store computed statistical values (HHCF, PSDF, DH, etc.) to separate files.
import gwyutils def write_to_file(dataline, filename): # write content of dataline to specified file f = open(filename, "w") data = line.get_data() for num in data: f.write(str(num)+"\n") f.close() # get active container c = gwy.gwy_app_data_browser_get_current(gwy.APP_CONTAINER) # get filename of active container filename = c.get_string_by_name("/filename") # remove extension from filename filebase = filename[0:-4] # call 'level' process module as interactive gwy.gwy_process_func_run("level", c, gwy.RUN_INTERACTIVE) # call 'remove scars' process module gwy.gwy_process_func_run("scars_remove", c, gwy.RUN_IMMEDIATE) # set colors of first datafield in active container c.set_string_by_name("/0/base/palette", "Green") # save fixed file gwy.gwy_file_save(c, filebase+"_fixed.gwy", gwy.RUN_NONINTERACTIVE) # export datafield from container c specified by name to png file gwyutils.save_dfield_to_png(c, "/0/data", filebase+"_fixed.png", gwy.RUN_INTERACTIVE) # get active datafield d = gwy.gwy_app_data_browser_get_current(gwy.APP_DATA_FIELD) # create dataline for storing results of following methods line = gwy.DataLine(1, 1, True) # Calculate one-dimensional autocorrelation function of a data field. d.hhcf(line, gwy.ORIENTATION_HORIZONTAL, gwy.INTERPOLATION_LINEAR, -1) # write values to file write_to_file(line, filebase+"_hhcf.txt") # Calculates one-dimensional power spectrum density function of a data field. d.psdf(line, gwy.ORIENTATION_HORIZONTAL, gwy.INTERPOLATION_LINEAR, gwy.WINDOWING_HANN, -1) # write values to file write_to_file(line, filebase+"_psdf.txt") # Calculates distribution of heights in a data field. d.dh(line, -1) # write values to file write_to_file(line, filebase+"_dh.txt") # Computes basic statistical quantities of a data field. avg, ra, rms, skew, kurtosis = d.get_stats() # Save statistical quantities to file f = open(filebase+"_stat.txt", "w") f.write("avg "+str(avg) +"\nra "+str(ra)+"\nrms "+str(rms)+"\nskew "\ +str(skew)+"\nkurtosis "+ str(kurtosis)) # close file f.close()
This script iterate thru open files (containers). Each datafield in every container is inverted, the pattern is changed and exported to PNG file.
import gwyutils # base name basename = "exported_png_%d.png" i = 0 # get list of available containers cons = gwy.gwy_app_data_browser_get_containers() # iterate thru containers and datafields for c in cons: # get directory of datafields where key is key in container dfields = gwyutils.get_data_fields_dir(c) for key in dfields.keys(): # get processed datafield object datafield = dfields[key] # retrieve datafield number in container from key (for example '/0/data') datafield_id = key.split('/')[1] # set palette of datafield c.set_string_by_name("/%s/base/palette" % datafield_id, "Spectral") # invert datafield values (processing section) datafield.invert(0, 0, 1) # request redraw before export datafield.data_changed() # export datafield to png, for the first time show export dialog if i == 0: gwyutils.save_dfield_to_png(c, key, basename % i, gwy.RUN_INTERACTIVE) else : gwyutils.save_dfield_to_png(c, key, basename % i, gwy.RUN_NONINTERACTIVE) i += 1 # request redraw datawindows with datafields datafield.data_changed()