# PALPAO: deformable mirror controller 

[![Build Status][travis]][travislink]  [![Coverage Status][coveralls]][coverallslink]  [![PyPI version][pypiversion]][pypiversionlink]

This is part a component of the Plico framework to control DMs (Alpao, MEMS)


[plico]: https://github.com/lbusoni/plico
[pysilico]: https://github.com/lbusoni/pysilico
[allied]: https://www.alliedvision.com
[travis]: https://travis-ci.com/lbusoni/palpao.svg?branch=master "go to travis"
[travislink]: https://travis-ci.com/lbusoni/palpao
[coveralls]: https://coveralls.io/repos/github/lbusoni/palpao/badge.svg?branch=master "go to coveralls"
[coverallslink]: https://coveralls.io/github/lbusoni/palpao
[pypiversion]: https://badge.fury.io/py/palpao.svg
[pypiversionlink]: https://badge.fury.io/py/palpao

## Installation

### Installing

From the wheel

```
pip install palpao-XXX.whl
```

In palpao source dir

```
pip install .
```

During development you want to update use

```
pip install -e .
```
that install a python egg with symlinks to the source directory in such 
a way that chages in the python code are immediately available without 
the need for re-installing (beware of conf/calib files!)

### Uninstall

```
pip uninstall palpao
```

### Config files

The application uses `appdirs` to locate configurations, calibrations 
and log folders: the path varies as it is OS specific. 
The configuration files are copied when the application is first used
from their original location in the python package to the final
destination, where they are supposed to be modified by the user.
The application never touches an installed file (no delete, no overwriting)

To query the system for config file location, in a python shell:

```
import palpao
palpao.defaultConfigFilePath
```


The user can specify customized conf/calib/log file path for both
servers and client (how? ask!)


## Usage

### Starting Server

```
palpao_start
```
Starts the 2 servers that control one device each.


### Using client 

In a Python / IPython shell:

```
In [1]: import palpao

In [2]: dm1=palpao.DeformableMirror('AlpaoDM277')

In [3]: dm2=palpao.DeformableMirror('MemsMultiDM')

In [4]: dm1.getSnapshot('boo')
Out[4]: {'boo.COMMAND_COUNTER': 0, 'boo.SERIAL_NUMBER': '1', 'boo.STEP_COUNTER': 45956}

In [5]: dm1.applyZonalCommand(np.ones(277))

In [6]: dm1.getZonalCommand()
Out[6]:
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1., 1., 1.])

In [7]: dm1.getSnapshot('boo')
Out[7]: {'boo.COMMAND_COUNTER': 1, 'boo.SERIAL_NUMBER': '1', 'boo.STEP_COUNTER': 83589}

In [8]: dm2.getSnapshot('tux')
Out[8]:
{'tux.COMMAND_COUNTER': 0,
 'tux.SERIAL_NUMBER': '234',
 'tux.STEP_COUNTER': 95980}
```


### Terminal

An ipython terminal with palpao embedded

```
palpao_terminal
```

### Stopping Palpao

To kill the servers

```
palpao_stop
```

More hard:

```
palpao_kill_all
```




## Administration Tool

For developers.


### Testing
Never commit before tests are OK!
To run the unittest and integration test suite execute in palpao source dir

```
python setup.py test
```


### Creating a Conda environment
Use the Anaconda GUI or in terminal

```
conda create --name palpao 
```

To create an environment with a specific python version

```
conda create --name palpao26  python=2.6
```


It is better to install available packages from conda instead of pip. 

```
conda install --name palpao matplotlib scipy ipython numpy
```

### Packaging and distributing

See https://packaging.python.org/tutorials/distributing-packages/#

To make a source distribution

```
python setup.py sdist
```

and the tar.gz is created in palpao/dist


If it is pure Python and works on 2 and 3 you can make a universal wheel 

```
python setup.py bdist_wheel --universal
```

Otherwise do a pure wheel

```
python setup.py bdist_wheel
```

The wheels are created in palpao/dist. I suppose one can trash palpao/build now and distribute the files in palpao/dist


To upload on pip (but do you really want to make it public?)

```
twine upload dist/*
```
