"""Example Google style docstrings.
This module demonstrates documentation as specified by the `Google Python
Style Guide`_. Docstrings may extend over multiple lines. Sections are created
with a section header and a colon followed by a block of indented text.
Example:
Examples can be given using either the ``Example`` or ``Examples``
sections. Sections support any reStructuredText formatting, including
literal blocks::
$ python example_google.py
Section breaks are created by resuming unindented text. Section breaks
are also implicitly created anytime a new section starts.
Attributes:
module_level_variable1 (int): Module level variables may be documented in
either the ``Attributes`` section of the module docstring, or in an
inline docstring immediately following the variable.
Either form is acceptable, but the two should not be mixed. Choose
one convention to document module level variables and be consistent
with it.
.. _Google Python Style Guide:
http://google.github.io/styleguide/pyguide.html
"""
from __future__ import division, absolute_import, print_function
__author__ = 'andrea tramacere'
import numpy as np
from ast import literal_eval
[docs]class Quantity(object):
def __init__(self,values,units=None,allowed_units=[],copy=True,name=None):
self._set_values(values,copy)
self._units=units
self._allowed_units=allowed_units
self._check_units()
self._name=name
[docs] def view(self):
if np.isscalar(self.values):
return np.array(self.values)
else:
return self.values
def __repr__(self,hide_values=True):
prefixstr = '<' + self.__class__.__name__ + ' name=%s'%self._name+' ' +' shape=',self.shape
if hide_values==False:
arrstr = np.array2string(self.view(), separator=',',
prefix=prefixstr)
else:
arrstr=''
return '{0}{1}{2:s}>\n'.format(prefixstr, arrstr, ' observables=%s'%self.units)
@property
def name(self):
if self._name==None:
return 'No'
else:
return self._name
@property
def units(self):
if self._units==None:
return 'No'
else:
return self._units
@property
def allowed_units(self):
return self._allowed_units
@property
def shape(self):
if np.isscalar(self.values):
return np.shape(self._values)
else:
return self._values.shape
@property
def values(self):
return self._values
@values.setter
def values(self,values):
self._values=self._set_values(values,copy=False)
def _set_allowed_units(self,allowed_units):
if type(allowed_units)==list:
return allowed_units
else:
return [allowed_units]
def _set_values(self,values,copy):
if type(values)==list:
#list to np.ndarray
for ID,item in enumerate(values):
v=self._check_is_number(item)
if v is not False:
values[ID]=v
else:
values[ID]=False
self._values= np.array([x for x in values if x is not False])
elif type(values)==np.ndarray:
#np.array
if copy==False:
self._values= self._check_is_number(values)
else:
self._values= np.copy(self._check_is_number(values))
elif np.shape(values)==():
#scalar
v=self._check_is_number(values)
if v is not False:
self._values= v
else:
raise ValueError ('values are not convertible to numbers')
@staticmethod
def _check_is_number(v):
if type(v)==str:
try:
return literal_eval(v)
except ValueError:
return False
else:
return v
def _check_units(self,unit_to_check=None):
if unit_to_check is None:
unit_to_check=self._units
if self._allowed_units!=[] and self._allowed_units!=None:
if unit_to_check not in self._allowed_units:
raise ValueError(""" unit '%s' is not valid , use one of the folowing %s """%(unit_to_check,self.allowed_units))
else:
pass
def _convert(self,new_units,func,inplace=False):
self._check_units(unit_to_check=new_units)
if inplace==True:
self.values=func(self.values)
self._units=new_units
else:
return func(self.values)
[docs]class Angle(Quantity):
def __init__(self,value,units='deg',copy=True,name=None):
super(Angle,self).__init__(value,units,['rad','deg'],name=name,copy=copy)
@property
def rad(self):
if self._units=='deg':
return self._convert('rad',np.deg2rad,inplace=False)
else:
return self.values
@property
def to_rad(self,inplace=False):
if self._units=='deg':
return self._convert('rad',np.deg2rad,inplace=True)
else:
return self._values
@property
def deg(self,inplace=False):
if self._units=='rad':
return self._convert('deg',np.rad2deg,inplace=False)
else:
return self._values
@property
def to_deg(self,inplace=False):
if self._units=='rad':
return self._convert('deg',np.rad2deg,inplace=True)
else:
return self.values
[docs]class Distance(Quantity):
pass
[docs]class Pixel(Quantity):
def __init__(self,value,units='deg',copy=True):
super(Pixel,self).__init__(value,units,['cts'])