CLIPOL: a command line interface to IPOL
========================================


This project has two separate goals:

1) provide a command line interface to ipol articles
2) provide a unified IPOL interface for many languages (numpy, octave, lua, ...)

The idea is that each IPOL article can described by a single text file, written
in IDL (Ipol Description Language).  This file specifies the URL of the source
code of the article; the compilation instructions; the names, types and default
values of the input and output parameters; and the way to call the downloaded
code of the article.


EXAMPLE USAGE (in bash)
-----------------------

cp lena.png x.png
ipol lsd x.png y.asc             # line segment detector
ipol nlm sigma=20 x.png z.png    # non-local means denoiser
ipol phs x.png z.png f.tiff      # pyramidal horn-schunk optical flow
ipol tvl1 x.png z.png g.tiff     # TVL1 optical flow


EXAMPLE USAGE (in python)
-------------------------

import ipol                # ipol module
import iio                 # image input/output
x = iio.read("lena.png")   # x is an array of size 256x256
y = ipol.lsd(x)            # y is an array of size 351x7
z = ipol.nlm(x, sigma=20)  # z is like x, but denoised
f = ipol.phs(x, z)         # f is the horn-schunck flow from x to z
g = ipol.tvl1(x, z)        # f is the TVL1 flow from x to z


EXAMPLE IDL
-----------

NAME nlm
TITLE Non-Local Means Denoising
AUTHORS Antoni Buades, Bartomeu Coll, Jean-Michel Morel
SRC http://www.ipol.im/pub/art/2011/bcm_nlm/revisions/2021-08-22/nlmeansC.tar.gz

BUILD make
BUILD cp nlmeans_ipol $BIN/nlm

INPUT in image
INPUT sigma number 10    # sigma for the denoiser
OUTPUT out image

RUN nlm $in $sigma 0 $out dummy


INSTALLATION
------------

The whole implementation is contained on a single file "ipol.py", which is an
executable and importable python script.

bash: copy or link the file ipol.py to your path with name "ipol"
python: copy the file ipol.py to your python import path

also: pip install ipol  # does both things


FILES
-----

The IDL files of each IPOL algorithm are stored on the directory
"~/.config/ipol/idl/".   This can be created and filled-in manually, and the
files can be edited by hand using a text editor.  It can also be filled-in
automatically by running "ipol download_idls".

The downloaded and compiled sources, and the binaries, of an algorithm X are
stored on the directory "~/.cache/ipol/X" according to the following hierarchy:
	~/.cache/ipol/X/dl/src.tar.gz (original source code of the article)
	~/.cache/ipol/X/src/ (decompressed source code tree)
	~/.cache/ipol/X/bin/ (binary files associated to the article)
	~/.cache/ipol/X/tmp/ (temporary files created on each execution)

Each time that we want to run an algorithm "X", the file ~/.config/ipol/idl/X
is parsed and the tree under "~/.cache/ipol/X" is created if it didn't already
exist.  The original source code is downloaded and compiled locally.  Then the
algorithm is run to create the requested files.

Thus, for example, if on a new installation we run

$ ipol ace lena.png out1.png
$ ipol ace lena.png out2.png

The files out1.png and out2.png will be identical (a color-corrected version of
the lena image) but the first run will be much slower because the whole source
code of the ACE algorithm will be downloaded and compiled.  The second run will
be very fast.  Thus, to try the ACE algorithm with several values of alpha we
can do

for i in {1..8}; do
	ipol ace lena.png lena_ace_$i.png alpha=$i
done

You can delete and edit all the cached and config files by hand.  To remove the
cache and start anew simply delete the folder ~/.cache/ipol



DESIGN PRINCIPLES (in decreasing order of importance)
-----------------------------------------------------

0. the bash and python full interfaces are on the same, single file
1. adding a new ipol wrapper consists in writing a single text file
2. this text file must be language-agnostic
3. all functionalities exposed by the downloaded code can be accessed
4. it must be easy to write wrappers for many languages using exactly the same
   wrapper text files
5. important targets (in decreasing order): numpy, shell, octave, C, lua, C++
6. the interface must be as efficient as possible
7. it must be possible to call the original program in "raw" form
8. input parameters are raw strings, their verification is left to the backend
9. no dependency management: the system works only if the user has all the
   requirements already installed.  Otherwise, it fails at build or at run time.
X. hacks to compile and run the code are necessary and encouraged in the BUILD
   and RUN sections of the idl files.  This produces a unified database of
   simple modifications that can be pused upstream to increase the overall
   portability/reproducibility of the universe.


GENERIC INTERFACES
------------------

Each IPOL article exposes a single interface, in the form of a single function
with a well-defined signature.  The function receives an array of n objects and
returns an array of m objects, the numbers n and m are constant and fixed for
each article.

There are only THREE possible types of objects:

	- a multidimensional array of floats
	- a float
	- a string

If you need integer values or booleans, you put them inside floats.  Strings
are to be avoided unless really necessary (e.g., if your program deals with
text).

