Discussion:
[Gwyddion-users] Populating a DataField object from the gwy module
Mark S. Bentley
2014-07-02 11:04:32 UTC
Permalink
Dear all,

I have a (hopefully) straightforward question. I have all of my AFM
image and meta data in python (numpy array and dictionary) and want to
simply write to a Gwyddion native file. I have imported the gwy module,
created a new container and DataField object (initialise to the correct
size/number of pixels), set the meta data and channel title etc.
However, I can't find an easy way to populate the contents of the data
itself...

DataField.get_data() works fine, and returns the initialised zero
values. There is a function DataField.set_data() on inspecting the
object, but this is not listed in the API and I can't get it to work.

There was a similar question on the list a while back, which was solved
by using gwyutils. But I guess this only works inside of Gwyddion, and I
need something that will run standalone...

Calling DataField.set_val() in a loop works fine - is this the preferred
python option? The docs talk about using get_data() and referencing the
returned buffer, but I guess this comes directly from the underlying C
docs and is not relevant here..

Thanks for your help!

Mark
David Nečas (Yeti)
2014-07-02 12:05:25 UTC
Permalink
Post by Mark S. Bentley
I have a (hopefully) straightforward question. I have all of my AFM
image and meta data in python (numpy array and dictionary) and want to
simply write to a Gwyddion native file. I have imported the gwy module,
created a new container and DataField object (initialise to the correct
size/number of pixels), set the meta data and channel title etc.
However, I can't find an easy way to populate the contents of the data
itself...
DataField.get_data() works fine, and returns the initialised zero
values. There is a function DataField.set_data() on inspecting the
object, but this is not listed in the API and I can't get it to work.
There was a similar question on the list a while back, which was solved
by using gwyutils. But I guess this only works inside of Gwyddion, and I
need something that will run standalone...
No, it should work standalone also if you have gwyutils in the Python
path:

import gwy, gwyutils

d = gwy.DataField(200, 200, 1.0, 1.0, False)
a = gwyutils.data_field_data_as_array(d)
# Can also use numpy array functions here
for i in range(200):
for j in range(200):
a[i][j] = i-j

c = gwy.Container()
c['/0/data'] = d

gwy.gwy_file_save(c, 'z.gwy', gwy.RUN_NONINTERACTIVE)
Post by Mark S. Bentley
Calling DataField.set_val() in a loop works fine - is this the preferred
python option? The docs talk about using get_data() and referencing the
returned buffer, but I guess this comes directly from the underlying C
docs and is not relevant here..
If you have numpy then data_field_data_as_array() is better. The data
access is faster and you have high-level data operations available from
numpy. Otherwise set_val() is the way to modify data.

One caveat if you modify the data directly with numpy – it is necessary
to call d.invalidate() afterwards if you do continue doing anything
nontrivial with the field (just saving is OK). Otherwise various
functions can use stale cached information about properties of the
field, such as minimum and maximum values, leading to all kinds of odd
behaviour.

Unfortunately, gwy_data_field_invalidate() is a macro in C so it is not
actually possible to call d.invalidate() at this moment. I will have to
fix that by providing it also as a function that will be automatically
translated to Python.

Regards,

Yeti
Mark S. Bentley
2014-07-02 13:09:12 UTC
Permalink
Hi Yeti,

Thanks for the quick response!
Post by David Nečas (Yeti)
No, it should work standalone also if you have gwyutils in the Python
OK, looks like I need to manually add it. I previously used the PPA for
ubuntu but "import gwy" failed, so I built from source. Now gwy imports
but not gwyutils. On inspection, I see the source at
/usr/local/share/gwyddion/pygwy/gwyutils.py - after adding that to my
PYTHONPATH I can import fine, so I'll follow your suggestion and use
gwyutils.data_field_data_as_array.

Regards,

Mark

Loading...