more pydoc hacking

This commit is contained in:
John Cupitt 2014-11-14 10:07:04 +00:00
parent b45e6b4ec8
commit 742ff4c108
2 changed files with 190 additions and 167 deletions

20
TODO
View File

@ -1,5 +1,3 @@
- update python section in manual
- try: - try:
$ cd vips-x.x.x/libvips $ cd vips-x.x.x/libvips
@ -13,6 +11,24 @@
- python fitsload has both "access" and "sequential" as kwargs, is this right? - python fitsload has both "access" and "sequential" as kwargs, is this right?
why do we need both? why do we need both?
try:
$ vips fitsload
load a FITS image
usage:
fitsload filename out
where:
filename - Filename to load from, input gchararray
out - Output image, output VipsImage
optional arguments:
flags - Flags for this file, output VipsForeignFlags
disc - Open to disc, input gboolean
access - Required access pattern for this file, input VipsAccess
seq is not there ... do we need to hide deprecated?
check cplusplus as well
- test other arg types - test other arg types
input int works input int works

View File

@ -15,8 +15,8 @@
<refpurpose>How to use the VIPS library from Python</refpurpose> <refpurpose>How to use the VIPS library from Python</refpurpose>
</refnamediv> </refnamediv>
<refsect1 id="using-python"> <refsect1 id="python-intro">
<title>Using VIPS from Python</title> <title>Introduction</title>
<para> <para>
VIPS comes with a convenient, high-level Python API based VIPS comes with a convenient, high-level Python API based
on <code>gobject-introspection</code>. As long as you can get GOI on <code>gobject-introspection</code>. As long as you can get GOI
@ -28,8 +28,7 @@
on your platform. on your platform.
</para> </para>
<example> <para>
<title>VIPS from Python example</title>
<programlisting language="Python"> <programlisting language="Python">
#!/usr/bin/python #!/usr/bin/python
@ -48,40 +47,34 @@ im = im.conv(mask)
im.write_to_file(sys.argv[2]) im.write_to_file(sys.argv[2])
</programlisting> </programlisting>
</example>
<para> Reading this example, the first line loads the input file. You can append
Reading the example, the first line loads the input file. You can append
load options to the argument list as keyword arguments, for example: load options to the argument list as keyword arguments, for example:
<programlisting language="Python"> <programlisting language="Python">
im = Vips.Image.new_from_file(sys.argv[1], access = Vips.Access.SEQUENTIAL) im = Vips.Image.new_from_file(sys.argv[1], access = Vips.Access.SEQUENTIAL)
</programlisting> </programlisting>
See the various loaders for a list of the available options for each See the various loaders for a list of the available options
file format. The C for each file format. The C equivalent to this function,
equivalent to this function, vips_image_new_from_file(), has more vips_image_new_from_file(), has more extensive documentation. Try
extensive documentation. <code>help(Vips.Image)</code> to see a list of all the image
constructors --- you can load from memory, or create from an array,
for example.
</para> </para>
<para> <para>
There are The next line crops 100 pixels off every edge. Try
several other constructors: you can load a formatted image (for example, <code>help(im.extract_area)</code> and the C API docs for
a JPEG format image) from a string with <code>.new_from_buffer()</code>. vips_extract_area() for details. You can use <code>.crop()</code> as a
synonym, if you like. <code>im.width</code> gets the image width in
pixels, see <code>help(Vips.Image)</code> and vips_image_get_width()
and friends for a list of the other getters.
</para> </para>
<para> <para>
The next line crops 100 pixels off every edge. See the docs for the C The <code>similarity</code> line shrinks by 10%. By default it uses
function vips_extract_area() for details of the parameters. You can use bilinear interpolation, use <code>interpolate</code> to pick another
<code>.crop()</code> as a synonym, if you like.
<code>im.width</code> gets the image width in pixels, see
vips_image_get_width() and friends for a list of the other getters.
</para>
<para>
The <code>similarity</code> line shrinks by 10%, see the docs for the C
function vips_similarity() for details. By default it uses bilinear
interpolation, use <code>interpolate</code> to pick another
interpolator, for example: interpolator, for example:
<programlisting language="Python"> <programlisting language="Python">
@ -124,139 +117,134 @@ from gi.repository import Vips
from your code, and they will call into libvips for you. C functions from your code, and they will call into libvips for you. C functions
become Python functions in an obvious way: vips_operation_new(), become Python functions in an obvious way: vips_operation_new(),
for example, the constructor for the class #VipsOperation, becomes for example, the constructor for the class #VipsOperation, becomes
<code>Vips.Operation.new()</code>. <code>Vips.Operation.new()</code>. See the C API docs for details.
</para> </para>
<para> <para>
Using libvips like this is possible, but a bit painful. To make the API Using libvips like this is possible, but a bit painful. To make the API
seem more pythonesque, vips includes a set of overrides which wrap up seem more pythonesque, vips includes a set of overrides which form a
the bare functions created by gobject-introspection in a nicer package. layer over the bare functions created by gobject-introspection.
These overrides do the following things: </para>
</refsect1>
<itemizedlist> <refsect1 id="python-wrapping">
<title>Automatic wrapping</title>
<para>
The overrides intercept member lookup
on the <code>Vips.Image</code> class and look for vips operations
with that name. So the vips operation "add", which appears in the
C API as vips_add(), appears in Python as
<code>image.add()</code>.
</para>
<listitem> <para>
<para><emphasis>Automatic wrapping of vips operations</emphasis> </para> The first input image argument becomes the <code>self</code>
argument. If there are no input image arguments, the operation
appears as a class member. Optional input arguments become
keyword arguments. The result is a list of all the output
arguments, or a single output if there is only one.
</para>
<para> <para>
It intercepts member lookup Optional output arguments are enabled with a boolean keyword
on the <code>Vips.Image</code> class and looks for vips operations argument of that name. For example, "min" (the operation which
with that name. So the vips operation "add", which appears in the appears in the C API as vips_min()), can be called like this:
C API as vips_add(), appears in Python as
<code>Vips.Image.add</code>.
</para>
</listitem>
<listitem>
<para><emphasis>Add docstrings</emphasis> </para>
<para>
Try <code>help(Vips.Image)</code>, or something like:
<programlisting language="Python">
image = Vips.Image.new_from_file("x.jpg")
help(image.add)
</programlisting>
For any operator it'll list the required and optional input and
output arguments, using all the rules listed below. This plus the
C API docs should be enough to answer most questions. IDEs should
display the help text automatically as you work.
</para>
</listitem>
<listitem>
<para><emphasis>Automatic wrapping of operation arguments</emphasis> </para>
<para>
The first input image argument becomes the <code>self</code>
argument. If there are no input image arguments, the operation
appears as a class member. Optional input arguments become
keyword arguments. The result is a list of all the output
arguments, or a single output if there is only one.
</para>
<para>
Optional output arguments are enabled with a boolean keyword
argument of that name. For example, "min" (the operation which
appears in the C API as vips_min()), can be called like this:
<programlisting language="Python"> <programlisting language="Python">
min_value = im.min() min_value = im.min()
</programlisting> </programlisting>
and <code>min_value</code> will be a floating point value giving and <code>min_value</code> will be a floating point value giving
the minimum value in the image. "min" can also find the position the minimum value in the image. "min" can also find the position
of the minimum value with the <code>x</code> and <code>y</code> of the minimum value with the <code>x</code> and <code>y</code>
optional output arguments. Call it like this: optional output arguments. Call it like this:
<programlisting language="Python"> <programlisting language="Python">
min_value, x_pos, y_pos = im.min(x = True, y = True) min_value, x_pos, y_pos = im.min(x = True, y = True)
</programlisting> </programlisting>
Although in this case, the <code>.minpos()</code> convenience Although in this case, the <code>.minpos()</code> convenience
function would be simpler. function would be simpler.
</para> </para>
</listitem>
<listitem> <para>
<para><emphasis>Automatic type conversion</emphasis></para> Because operations are member functions and return the result image,
<para> you can chain them. For example, you can write:
The override looks at the type of
argument required by the operation and converts the value you
supply, when it can. For example, "linear" takes a
#VipsArrayDouble as an argument for the constant to use for
multiplication. You can supply this value as an integer, a float,
or some kind of compound object and it will be converted for you.
</para>
<para> <programlisting language="Python">
It does a couple of more ambitious conversions. It will result_image = image.sin().pow(2)
automatically convert to and from the various vips types, </programlisting>
like #VipsBlob and #VipsArrayImage. For example, you can read the
ICC profile out of an image like this: to calculate the square of the sine for each pixel. There is also a
full set of arithmetic operator overloads, see below.
</para>
<para>
VIPS types are also automatically wrapped. The override looks
at the type of argument required by the operation and converts
the value you supply, when it can. For example, "linear" takes a
#VipsArrayDouble as an argument for the set of constants to use for
multiplication. You can supply this value as an integer, a float,
or some kind of compound object and it will be converted for you.
You can write:
<programlisting language="Python">
result_image = image.linear(1, 3)
result_image = image.linear(12.4, 13.9)
result_image = image.linear([1, 2, 3], [4, 5, 6])
result_image = image.linear(1, [4, 5, 6])
</programlisting>
And so on. A set of overloads are defined for <code>.linear()</code>,
see below.
</para>
<para>
It does a couple of more ambitious conversions. It will
automatically convert to and from the various vips types,
like #VipsBlob and #VipsArrayImage. For example, you can read the
ICC profile out of an image like this:
<programlisting language="Python"> <programlisting language="Python">
profile = im.get_value("icc-profile-data") profile = im.get_value("icc-profile-data")
</programlisting> </programlisting>
and <code>profile</code> will be a string. and <code>profile</code> will be a string.
</para> </para>
<para> <para>
If an operation If an operation takes several input images, you can use a constant
takes several input images, you can use a constant for all but for all but one of them and the wrapper will expand the constant
one of them and the wrapper will make a constant image for you. to an image for you. For example, <code>.ifthenelse()</code> uses
For example, <code>.ifthenelse()</code> uses a condition image to a condition image to pick pixels between a then and an else image:
pick pixels between a then and an else image:
<programlisting language="Python"> <programlisting language="Python">
result_image = condition_image.ifthenelse(then_image, else_image) result_image = condition_image.ifthenelse(then_image, else_image)
</programlisting> </programlisting>
You can use a constant instead of either the then or the else You can use a constant instead of either the then or the else
parts, and it will be expanded to an image for you. If you use a parts, and it will be expanded to an image for you. If you use a
constant for both then and else, it will be expanded to match the constant for both then and else, it will be expanded to match the
condition image. For example: condition image. For example:
<programlisting language="Python"> <programlisting language="Python">
result_image = condition_image.ifthenelse([0, 255, 0], [255, 0, 0]) result_image = condition_image.ifthenelse([0, 255, 0], [255, 0, 0])
</programlisting> </programlisting>
Will make an image where true pixels are green and false pixels Will make an image where true pixels are green and false pixels
are red. are red.
</para> </para>
<para> <para>
This is useful for <code>.bandjoin()</code>, the thing to join This is useful for <code>.bandjoin()</code>, the thing to join
two, or a set of images up bandwise. You can write: two or more images up bandwise. You can write:
<programlisting language="Python"> <programlisting language="Python">
rgba = rgb.bandjoin(255) rgba = rgb.bandjoin(255)
</programlisting> </programlisting>
to add a constant 255 band to an image, perhaps to add an alpha to add a constant 255 band to an image, perhaps to add an alpha
channel. Of course you can also write: channel. Of course you can also write:
<programlisting language="Python"> <programlisting language="Python">
result_image = image1.bandjoin(image2) result_image = image1.bandjoin(image2)
@ -265,70 +253,89 @@ result_image = Vips.Image.bandjoin([image1, image2, image3])
result_image = image1.bandjoin([image2, 255]) result_image = image1.bandjoin([image2, 255])
</programlisting> </programlisting>
and so on. and so on.
</para> </para>
</listitem> </refsect1>
<listitem> <refsect1 id="python-doc">
<para><emphasis>Exceptions</emphasis></para> <title>Automatic docstrings</title>
<para>
<para> Try <code>help(Vips)</code> for everything,
The wrapper spots errors from vips operations and raises the <code>help(Vips.Image)</code> for something slightly more digestible, or
<code>Vips.Error</code> exception. You can catch it in the something like <code>help(Vips.Image.black)</code> for help on a
usual way. The <code>.detail</code> member gives the detailed specific class member.
error message. </para>
</para>
</listitem>
<listitem> <para>
<para><emphasis>Overloads</emphasis></para> You can't get help on dynamically bound member functions like
<code>.add()</code> this way. Instead, make an image and get help
from that, for example:
<para> <programlisting language="Python">
The wrapper defines the usual set of arithmetic, boolean and image = Vips.Image.new_from_file("x.jpg")
relation overloads on help(image.add)
<code>image</code>. You can mix images, constants and lists of </programlisting>
constants (almost) freely.
</para>
</listitem>
<listitem> And you'll get a summary of the operator's behaviour and how the
<para><emphasis>Expansions</emphasis></para> arguments are represented in Python. Use the C API docs for more detail.
</para>
</refsect1>
<para> <refsect1 id="python-exceptions">
Some vips operators take an enum to select an action, for example <title>Exceptions</title>
<code>.math()</code> can be used to calculate sine of every pixel <para>
like this: The wrapper spots errors from vips operations and raises the
<code>Vips.Error</code> exception. You can catch it in the
usual way. The <code>.detail</code> member gives the detailed
error message.
</para>
</refsect1>
<refsect1 id="python-overloads">
<title>Overloads</title>
<para>
The wrapper defines the usual set of arithmetic, boolean and
relational overloads on
<code>image</code>. You can mix images, constants and lists of
constants (almost) freely. For example, you can write:
<programlisting language="Python">
result_image = ((image * [1, 2, 3]).abs() &lt; 128) | 4
</programlisting>
</para>
</refsect1>
<refsect1 id="python-expansions">
<title>Expansions</title>
<para>
Some vips operators take an enum to select an action, for example
<code>.math()</code> can be used to calculate sine of every pixel
like this:
<programlisting language="Python"> <programlisting language="Python">
result_image = image.math(Vips.OperationMath.SIN) result_image = image.math(Vips.OperationMath.SIN)
</programlisting> </programlisting>
This is annoying, so the wrapper expands all these enums into This is annoying, so the wrapper expands all these enums into
separate members named after the enum. So you can write: separate members named after the enum. So you can write:
<programlisting language="Python"> <programlisting language="Python">
result_image = image.sin() result_image = image.sin()
</programlisting> </programlisting>
See <code>help(Vips.Image)</code> for a list. See <code>help(Vips.Image)</code> for a list.
</para> </para>
</listitem> </refsect1>
<listitem> <refsect1 id="python-utility">
<para><emphasis>Utility functions</emphasis></para> <title>Convenience functions</title>
<para>
<para> The wrapper defines a few extra useful utility functions:
The wrapper defines a few extra useful utility functions: <code>.get_value()</code>, <code>.set_value()</code>
<code>.get_value()</code>, <code>.set_value()</code> <code>.bandsplit()</code>, <code>.maxpos()</code>
<code>.bandsplit()</code>, <code>.maxpos()</code> <code>.minpos()</code>.
<code>.minpos()</code>. Again, see <code>help(Vips.Image)</code> for a list.
Again, see <code>help(Vips.Image)</code> for a list.
</para>
</listitem>
</itemizedlist>
</para> </para>
</refsect1> </refsect1>
</refentry> </refentry>