Closed stephandooper closed 4 months ago
Hello @stephandooper,,
xres
is always in pixels per millimetre, so yes, 1000.0 / xres
ought to get you microns per pixel.
Python doesn't make it easy to add methods or properties to an existing class -- you're supposed to subclass objects to extend them. Ruby (for example) lets you extend classes in any crazy way you like, but python is much more opinionated.
libvips supports arbitrary metadata, so you could use that system. Perhaps:
image.set_type(pyvips.GValue.gdouble_type, "mpp", 180.0)
That adds a field called mpp
(microns per pixel) to that image with a value of 180.0. Some time later you can fetch it with eg.:
mpp = image.get("mpp")
It'll appear in get_fields()
.
In my opinion, subclassing Image
is probably cleaner and safer, but I'm sure there are good arguments either way.
Hi jcupitt,
Thanks for your prompt response. I indeed found that using image.set_type
is a lot easier than directly subclassing, and I believe it will suit most of my needs for now.
That being said, I wanted to share my experience of subclassing the Image class directly in case anyone else has a similar question:
Consider the following example where I want to open a new image from a file, using the subclass:
class ExtendedImage(pyvips.Image):
def some_silly_function(self):
print("hello world")
img = ExtendedImage.new_from_file("/data/temporary/stephan/normal_001.tif")
print(img)
print(type(img))
print(img.some_silly_function())
Would lead to the following error:
<pyvips.Image 49152x54272 uchar, 3 bands, srgb>
<class 'pyvips.vimage.Image'>
VipsOperation: class "some_silly_function" not found
So it returns a regular pyvips.vimage.Image
object, which makes sense, because img.image.new_from_file
is a static method that calls pyvips.Operation.call()
. If I want to change this, then I would have to alter the Operation
class as well (and perhaps others), is that correct?
Ahem you're right, I've never tried making a functioning subclass of pyvips.Image
myself.
You'd need to experiment a bit, perhaps intercepting __getattr__
and using a metaclass to control what methods get passed down to pyvips.Image
and how the return result is wrapped.
Thanks, your advise is much appreciated. I'll try tinkering with those options! I'll close this issue for now.
Hi!
As the title suggests, I was wondering if it's possible to add attributes or methods to the pyvips.Image class. The reason why I am asking is that I am working with pathology data, and I found that if I am writing these images to tif, the information about the magnification is either only in the metadata accessible in
img.get_fields()
, which differs per vendor (svs, tif, mrxs, ...) or viaxres
Specifically, in the following example I am reading an image with a magnification of 0,243 micron per pixels. However, the "xres" property is in dots per inch (I think?), so I have to convert this back into micron per pixels for this to work
output:
To keep things simple: I wanted to make life a little easier by adding an attribute to the Image class, so that I can fetch the information whenever I needed it, e.g. via
img.spacings
which would yield a list of the spacings in micron per pixels, instead of the dots per inch thatimg.xres
would yield. Would this at all be possible? and what about methods? My hunch after tinkering around is that it's not that simple :)If it's not directly possible, would it be possibe/recommended to create a new field that would be accesible via
img.get_fields
?