<commit_before>
import sys
import logging
import unittest
import threading
import random
import time
import copy

import numpy as np
import epics

from ophyd.signal import (Signal, EpicsSignal, EpicsSignalRO)
from ophyd.utils import (ReadOnlyError, TimeoutError)

logger = logging.getLogger(__name__)

class FakeEpicsPV(object):
    _connect_delay = (0.05, 0.1)
    _update_rate = 0.1
    fake_values = (0.1, 0.2, 0.3)
    _pv_idx = 0

    def __init__(self, pvname, form=None,
                 callback=None, connection_callback=None,
                 auto_monitor=True, enum_strs=None,
                 **kwargs):

        self._pvname = pvname
        self._callback = callback
        self._connection_callback = connection_callback
        self._form = form
        self._auto_monitor = auto_monitor
        self._value = self.fake_values[0]
        self._connected = False
        self.enum_strs = enum_strs
        FakeEpicsPV._pv_idx += 1
        self._idx = FakeEpicsPV._pv_idx

        self._update = True

        self._lock = threading.Lock()
        self._thread = threading.Thread(target=self._update_loop)
        self._thread.setDaemon(True)
        self._thread.start()

        # callbacks mechanism copied from pyepics
        self.callbacks = {}

        if callback:
            self.add_callback(callback)

    def get_ctrlvars(self):
        pass

    @property
    def connected(self):
        return self._connected

    def wait_for_connection(self, timeout=None):
        if self._pvname in ('does_not_connect', ):
            return False

        while not self._connected:
            time.sleep(0.05)

        return True

    def _update_loop(self):
        time.sleep(random.uniform(*self._connect_delay))
        if self._connection_callback is not None:
            self._connection_callback(pvname=self._pvname, conn=True, pv=self)

        if self._pvname in ('does_not_connect', ):
            return

        self._connected = True
        last_value = None

        while True:
            with self._lock:
                if self._update:
                    self._value = random.choice(self.fake_values)

                if self._value != last_value:
                    sys.stdout.flush()
                    self.run_callbacks()
                    last_value = self._value

                time.sleep(self._update_rate)

            time.sleep(0.01)

    @property
    def lower_ctrl_limit(self):
        return min(self.fake_values)

    @property
    def upper_ctrl_limit(self):
        return max(self.fake_values)

    def run_callbacks(self):
        for index in sorted(list(self.callbacks.keys())):
            self.run_callback(index)

    def run_callback(self, index):
        fcn, kwargs = self.callbacks[index]
        kwd = dict(pvname=self._pvname,
                   count=1,
                   nelm=1,
                   type=None,
                   typefull=None,
                   ftype=None,
                   access='rw',
                   chid=self._idx,
                   read_access=True,
                   write_access=True,
                   value=self.value,
                   )

        kwd.update(kwargs)
        kwd['cb_info'] = (index, self)
        if hasattr(fcn, '__call__'):
            fcn(**kwd)

    def add_callback(self, callback=None, index=None, run_now=False,
                     with_ctrlvars=True, **kw):
        if hasattr(callback, '__call__'):
            if index is None:
                index = 1
                if len(self.callbacks) > 0:
                    index = 1 + max(self.callbacks.keys())
            self.callbacks[index] = (callback, kw)

        if run_now:
            if self.connected:
                self.run_callback(index)
        return index

    def remove_callback(self, index=None):
        if index in self.callbacks:
            self.callbacks.pop(index)

    def clear_callbacks(self):
        self.callbacks = {}

    @property
    def precision(self):
        return 0

    @property
    def units(self):
        return str(None)

    @property
    def timestamp(self):
        return time.time()

    @property
    def pvname(self):
        return self._pvname

    @property
    def value(self):
        return self._value

    def __repr__(self):
        return '<FakePV %s value=%s>' % (self._pvname, self.value)

    def get(self, as_string=False, use_numpy=False,
            use_monitor=False):
        if as_string:

            if isinstance(self.value, list):
                if self.enum_strs:
                    return [self.enum_strs[_] for _ in self.value]
                return list(self.value)
            if isinstance(self.value, str):
                return self.value
            else:
                if self.enum_strs:
                    return self.enum_strs[self.value]
                return str(self.value)
        elif use_numpy:
            return np.array(self.value)
        else:
            return self.value

    def put(self, value, wait=False, timeout=30.0,
            use_complete=False, callback=None, callback_data=None):

        with self._lock:
            self._update = False
            self._value = value

class FakeEpicsWaveform(FakeEpicsPV):
    strings = ['abcd', 'efgh', 'ijkl']
    fake_values = [[ord(c) for c in s] + [0]
                   for s in strings]
    auto_monitor = False
    form = 'time'

def setUpModule():
    epics._PV = epics.PV
    epics.PV = FakeEpicsPV

def tearDownModule():
    logger.debug('Cleaning up')
    epics.PV = epics._PV

class FakePVTests(unittest.TestCase):
    def test_fakepv(self):
        pvname = 'fakepv_nowaythisexists' * 10

        info = dict(called=False)

        def conn(**kwargs):
            info['conn'] = True
            info['conn_kw'] = kwargs

        def value_cb(**kwargs):
            info['value'] = True
            info['value_kw'] = kwargs

        pv = epics.PV(pvname, callback=value_cb, connection_callback=conn,
                      )

        if not pv.wait_for_connection():
            raise ValueError('should return True on connection')

        self.assertEquals(pv.pvname, pvname)

        pv._update_rate = 0.5
        time.sleep(0.2)

        self.assertTrue(info['conn'])
        self.assertTrue(info['value'])
        self.assertEquals(info['value_kw']['value'], pv.value)

class SignalTests(unittest.TestCase):
    def test_signal_base(self):
        start_t = time.time()

        name = 'test'
        value = 10.0
        signal = Signal(name=name, value=value, timestamp=start_t)
        signal.wait_for_connection()

        self.assertTrue(signal.connected)
        self.assertEquals(signal.name, name)
        self.assertEquals(signal.value, value)
        self.assertEquals(signal.get(), value)
        self.assertEquals(signal.timestamp, start_t)

        info = dict(called=False)

        def _sub_test(**kwargs):
            info['called'] = True
            info['kw'] = kwargs

        signal.subscribe(_sub_test, run=False)
        self.assertFalse(info['called'])

        signal.value = value
        signal.clear_sub(_sub_test)

        signal.subscribe(_sub_test, run=False)
        signal.clear_sub(_sub_test, event_type=signal.SUB_VALUE)

        kw = info['kw']
        self.assertIn('value', kw)
        self.assertIn('timestamp', kw)
        self.assertIn('old_value', kw)

        self.assertEquals(kw['value'], value)
        self.assertEquals(kw['old_value'], value)
        self.assertEquals(kw['timestamp'], signal.timestamp)

        # readback callback for soft signal
        info = dict(called=False)
        signal.subscribe(_sub_test, event_type=Signal.SUB_VALUE,
                         run=False)
        self.assertFalse(info['called'])
        signal.put(value + 1)
        self.assertTrue(info['called'])

        signal.clear_sub(_sub_test)
        kw = info['kw']

        self.assertIn('value', kw)
        self.assertIn('timestamp', kw)
        self.assertIn('old_value', kw)

        self.assertEquals(kw['value'], value + 1)
        self.assertEquals(kw['old_value'], value)
        self.assertEquals(kw['timestamp'], signal.timestamp)

        signal.trigger()
        signal.read()
        signal.describe()
        signal.read_configuration()
        signal.describe_configuration()

        eval(repr(signal))

    def test_signal_copy(self):
        start_t = time.time()

        name = 'test'
        value = 10.0
        signal = Signal(name=name, value=value, timestamp=start_t)
        sig_copy = copy.copy(signal)

        self.assertEquals(signal.name, sig_copy.name)
        self.assertEquals(signal.value, sig_copy.value)
        self.assertEquals(signal.get(), sig_copy.get())
        self.assertEquals(signal.timestamp, sig_copy.timestamp)

class EpicsSignalTests(unittest.TestCase):
    def test_rw_removal(self):
        # rw kwarg is no longer used
        with self.assertRaises(RuntimeError):
            EpicsSignal('readpv', rw=False)

        with self.assertRaises(RuntimeError):
            EpicsSignal('readpv', rw=True)

    def test_epicssignal_readonly(self):
        epics.PV = FakeEpicsPV

        signal = EpicsSignalRO('readpv')
        signal.wait_for_connection()

        signal.value

        with self.assertRaises(ReadOnlyError):
            signal.value = 10

        with self.assertRaises(ReadOnlyError):
            signal.put(10)

        # vestigial, to be removed
        with self.assertRaises(AttributeError):
            signal.setpoint_ts

        # vestigial, to be removed
        with self.assertRaises(AttributeError):
            signal.setpoint

        signal.precision
        signal.timestamp
        signal.limits

        signal.read()
        signal.describe()
        signal.read_configuration()
        signal.describe_configuration()

        eval(repr(signal))
        time.sleep(0.2)

    def test_epicssignal_readwrite_limits(self):
        epics.PV = FakeEpicsPV

        signal = EpicsSignal('readpv', write_pv='readpv',
                             limits=True)

        signal.wait_for_connection()
        signal.check_value((signal.low_limit + signal.high_limit) / 2)

        try:
            signal.check_value(None)
        except ValueError:
            pass
        else:
            raise ValueError('value=None')

        try:
            signal.check_value(signal.low_limit - 1)
        except ValueError:
            pass
        else:
            raise ValueError('lower limit %s' % (signal.limits, ))

        try:
            signal.check_value(signal.high_limit + 1)
        except ValueError:
            pass
        else:
            raise ValueError('upper limit')

    def test_epicssignal_readwrite(self):
        epics.PV = FakeEpicsPV

        signal = EpicsSignal('readpv', write_pv='writepv')
        signal.wait_for_connection()

        self.assertEquals(signal.setpoint_pvname, 'writepv')
        self.assertEquals(signal.pvname, 'readpv')
        signal.value

        signal._update_rate = 2
        time.sleep(0.2)

        value = 10
        signal.value = value
        signal.setpoint = value
        self.assertEquals(signal.setpoint, value)
        signal.setpoint_ts

        signal.limits
        signal.precision
        signal.timestamp

        signal.read()
        signal.describe()
        signal.read_configuration()
        signal.describe_configuration()

        eval(repr(signal))
        time.sleep(0.2)

    def test_epicssignal_waveform(self):
        epics.PV = FakeEpicsWaveform

        def update_cb(value=None, **kwargs):
            self.assertIn(value, FakeEpicsWaveform.strings)

        signal = EpicsSignal('readpv', string=True)
        signal.wait_for_connection()

        signal.subscribe(update_cb)
        self.assertIn(signal.value, FakeEpicsWaveform.strings)

    def test_no_connection(self):
        epics.PV = FakeEpicsPV
        # special case in FakeEpicsPV that returns false in wait_for_connection
        sig = EpicsSignal('does_not_connect')
        self.assertRaises(TimeoutError, sig.wait_for_connection)

        sig = EpicsSignal('does_not_connect')
        self.assertRaises(TimeoutError, sig.put, 0.0)
        self.assertRaises(TimeoutError, sig.get)

        sig = EpicsSignal('connects', write_pv='does_not_connect')
        self.assertRaises(TimeoutError, sig.wait_for_connection)

    def test_enum_strs(self):
        epics.PV = FakeEpicsPV
        sig = EpicsSignal('connects')
        sig.wait_for_connection()

        enums = ['enum_strs']

        # hack this onto the FakeEpicsPV
        sig._read_pv.enum_strs = enums

        self.assertEquals(sig.enum_strs, enums)

    def test_setpoint(self):
        epics.PV = FakeEpicsPV
        sig = EpicsSignal('connects')
        sig.wait_for_connection()

        sig.get_setpoint()
        sig.get_setpoint(as_string=True)

    def test_epicssignalro(self):
        # not in initializer parameters anymore
        self.assertRaises(TypeError, EpicsSignalRO, 'test',
                          write_pv='nope_sorry')

    def test_describe(self):
        epics.PV = FakeEpicsPV
        sig = EpicsSignal('my_pv')
        sig._write_pv.enum_strs = ('enum1', 'enum2')
        sig.wait_for_connection()

        sig.put(1)
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'integer')
        self.assertEquals(desc['shape'], [])
        self.assertIn('precision', desc)
        self.assertIn('enum_strs', desc)
        self.assertIn('upper_ctrl_limit', desc)
        self.assertIn('lower_ctrl_limit', desc)

        sig.put('foo')
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'string')
        self.assertEquals(desc['shape'], [])

        sig.put(3.14)
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'number')
        self.assertEquals(desc['shape'], [])

        import numpy as np
        sig.put(np.array([1,]))
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'array')
        self.assertEquals(desc['shape'], [1,])

from . import main
is_main = (__name__ == '__main__')
main(is_main)
<commit_msg>TST: short-circuit fakeepicspv for auto_monitor<commit_after>
import sys
import logging
import unittest
import threading
import random
import time
import copy

import numpy as np
import epics

from ophyd.signal import (Signal, EpicsSignal, EpicsSignalRO)
from ophyd.utils import (ReadOnlyError, TimeoutError)

logger = logging.getLogger(__name__)

class FakeEpicsPV(object):
    _connect_delay = (0.05, 0.1)
    _update_rate = 0.1
    fake_values = (0.1, 0.2, 0.3)
    _pv_idx = 0
    auto_monitor = True

    def __init__(self, pvname, form=None,
                 callback=None, connection_callback=None,
                 auto_monitor=True, enum_strs=None,
                 **kwargs):

        self._pvname = pvname
        self._callback = callback
        self._connection_callback = connection_callback
        self._form = form
        self._auto_monitor = auto_monitor
        self._value = self.fake_values[0]
        self._connected = False
        self.enum_strs = enum_strs
        FakeEpicsPV._pv_idx += 1
        self._idx = FakeEpicsPV._pv_idx

        self._update = True

        self._lock = threading.Lock()
        self._thread = threading.Thread(target=self._update_loop)
        self._thread.setDaemon(True)
        self._thread.start()

        # callbacks mechanism copied from pyepics
        self.callbacks = {}

        if callback:
            self.add_callback(callback)

    def get_timevars(self):
        pass

    def get_ctrlvars(self):
        pass

    @property
    def connected(self):
        return self._connected

    def wait_for_connection(self, timeout=None):
        if self._pvname in ('does_not_connect', ):
            return False

        while not self._connected:
            time.sleep(0.05)

        return True

    def _update_loop(self):
        time.sleep(random.uniform(*self._connect_delay))
        if self._connection_callback is not None:
            self._connection_callback(pvname=self._pvname, conn=True, pv=self)

        if self._pvname in ('does_not_connect', ):
            return

        self._connected = True
        last_value = None

        while True:
            with self._lock:
                if self._update:
                    self._value = random.choice(self.fake_values)

                if self._value != last_value:
                    sys.stdout.flush()
                    self.run_callbacks()
                    last_value = self._value

                time.sleep(self._update_rate)

            time.sleep(0.01)

    @property
    def lower_ctrl_limit(self):
        return min(self.fake_values)

    @property
    def upper_ctrl_limit(self):
        return max(self.fake_values)

    def run_callbacks(self):
        for index in sorted(list(self.callbacks.keys())):
            self.run_callback(index)

    def run_callback(self, index):
        fcn, kwargs = self.callbacks[index]
        kwd = dict(pvname=self._pvname,
                   count=1,
                   nelm=1,
                   type=None,
                   typefull=None,
                   ftype=None,
                   access='rw',
                   chid=self._idx,
                   read_access=True,
                   write_access=True,
                   value=self.value,
                   )

        kwd.update(kwargs)
        kwd['cb_info'] = (index, self)
        if hasattr(fcn, '__call__'):
            fcn(**kwd)

    def add_callback(self, callback=None, index=None, run_now=False,
                     with_ctrlvars=True, **kw):
        if hasattr(callback, '__call__'):
            if index is None:
                index = 1
                if len(self.callbacks) > 0:
                    index = 1 + max(self.callbacks.keys())
            self.callbacks[index] = (callback, kw)

        if run_now:
            if self.connected:
                self.run_callback(index)
        return index

    def remove_callback(self, index=None):
        if index in self.callbacks:
            self.callbacks.pop(index)

    def clear_callbacks(self):
        self.callbacks = {}

    @property
    def precision(self):
        return 0

    @property
    def units(self):
        return str(None)

    @property
    def timestamp(self):
        return time.time()

    @property
    def pvname(self):
        return self._pvname

    @property
    def value(self):
        return self._value

    def __repr__(self):
        return '<FakePV %s value=%s>' % (self._pvname, self.value)

    def get(self, as_string=False, use_numpy=False,
            use_monitor=False):
        if as_string:

            if isinstance(self.value, list):
                if self.enum_strs:
                    return [self.enum_strs[_] for _ in self.value]
                return list(self.value)
            if isinstance(self.value, str):
                return self.value
            else:
                if self.enum_strs:
                    return self.enum_strs[self.value]
                return str(self.value)
        elif use_numpy:
            return np.array(self.value)
        else:
            return self.value

    def put(self, value, wait=False, timeout=30.0,
            use_complete=False, callback=None, callback_data=None):

        with self._lock:
            self._update = False
            self._value = value

class FakeEpicsWaveform(FakeEpicsPV):
    strings = ['abcd', 'efgh', 'ijkl']
    fake_values = [[ord(c) for c in s] + [0]
                   for s in strings]
    auto_monitor = False
    form = 'time'

def setUpModule():
    epics._PV = epics.PV
    epics.PV = FakeEpicsPV

def tearDownModule():
    logger.debug('Cleaning up')
    epics.PV = epics._PV

class FakePVTests(unittest.TestCase):
    def test_fakepv(self):
        pvname = 'fakepv_nowaythisexists' * 10

        info = dict(called=False)

        def conn(**kwargs):
            info['conn'] = True
            info['conn_kw'] = kwargs

        def value_cb(**kwargs):
            info['value'] = True
            info['value_kw'] = kwargs

        pv = epics.PV(pvname, callback=value_cb, connection_callback=conn,
                      )

        if not pv.wait_for_connection():
            raise ValueError('should return True on connection')

        self.assertEquals(pv.pvname, pvname)

        pv._update_rate = 0.5
        time.sleep(0.2)

        self.assertTrue(info['conn'])
        self.assertTrue(info['value'])
        self.assertEquals(info['value_kw']['value'], pv.value)

class SignalTests(unittest.TestCase):
    def test_signal_base(self):
        start_t = time.time()

        name = 'test'
        value = 10.0
        signal = Signal(name=name, value=value, timestamp=start_t)
        signal.wait_for_connection()

        self.assertTrue(signal.connected)
        self.assertEquals(signal.name, name)
        self.assertEquals(signal.value, value)
        self.assertEquals(signal.get(), value)
        self.assertEquals(signal.timestamp, start_t)

        info = dict(called=False)

        def _sub_test(**kwargs):
            info['called'] = True
            info['kw'] = kwargs

        signal.subscribe(_sub_test, run=False)
        self.assertFalse(info['called'])

        signal.value = value
        signal.clear_sub(_sub_test)

        signal.subscribe(_sub_test, run=False)
        signal.clear_sub(_sub_test, event_type=signal.SUB_VALUE)

        kw = info['kw']
        self.assertIn('value', kw)
        self.assertIn('timestamp', kw)
        self.assertIn('old_value', kw)

        self.assertEquals(kw['value'], value)
        self.assertEquals(kw['old_value'], value)
        self.assertEquals(kw['timestamp'], signal.timestamp)

        # readback callback for soft signal
        info = dict(called=False)
        signal.subscribe(_sub_test, event_type=Signal.SUB_VALUE,
                         run=False)
        self.assertFalse(info['called'])
        signal.put(value + 1)
        self.assertTrue(info['called'])

        signal.clear_sub(_sub_test)
        kw = info['kw']

        self.assertIn('value', kw)
        self.assertIn('timestamp', kw)
        self.assertIn('old_value', kw)

        self.assertEquals(kw['value'], value + 1)
        self.assertEquals(kw['old_value'], value)
        self.assertEquals(kw['timestamp'], signal.timestamp)

        signal.trigger()
        signal.read()
        signal.describe()
        signal.read_configuration()
        signal.describe_configuration()

        eval(repr(signal))

    def test_signal_copy(self):
        start_t = time.time()

        name = 'test'
        value = 10.0
        signal = Signal(name=name, value=value, timestamp=start_t)
        sig_copy = copy.copy(signal)

        self.assertEquals(signal.name, sig_copy.name)
        self.assertEquals(signal.value, sig_copy.value)
        self.assertEquals(signal.get(), sig_copy.get())
        self.assertEquals(signal.timestamp, sig_copy.timestamp)

class EpicsSignalTests(unittest.TestCase):
    def test_rw_removal(self):
        # rw kwarg is no longer used
        with self.assertRaises(RuntimeError):
            EpicsSignal('readpv', rw=False)

        with self.assertRaises(RuntimeError):
            EpicsSignal('readpv', rw=True)

    def test_epicssignal_readonly(self):
        epics.PV = FakeEpicsPV

        signal = EpicsSignalRO('readpv')
        signal.wait_for_connection()

        signal.value

        with self.assertRaises(ReadOnlyError):
            signal.value = 10

        with self.assertRaises(ReadOnlyError):
            signal.put(10)

        # vestigial, to be removed
        with self.assertRaises(AttributeError):
            signal.setpoint_ts

        # vestigial, to be removed
        with self.assertRaises(AttributeError):
            signal.setpoint

        signal.precision
        signal.timestamp
        signal.limits

        signal.read()
        signal.describe()
        signal.read_configuration()
        signal.describe_configuration()

        eval(repr(signal))
        time.sleep(0.2)

    def test_epicssignal_readwrite_limits(self):
        epics.PV = FakeEpicsPV

        signal = EpicsSignal('readpv', write_pv='readpv',
                             limits=True)

        signal.wait_for_connection()
        signal.check_value((signal.low_limit + signal.high_limit) / 2)

        try:
            signal.check_value(None)
        except ValueError:
            pass
        else:
            raise ValueError('value=None')

        try:
            signal.check_value(signal.low_limit - 1)
        except ValueError:
            pass
        else:
            raise ValueError('lower limit %s' % (signal.limits, ))

        try:
            signal.check_value(signal.high_limit + 1)
        except ValueError:
            pass
        else:
            raise ValueError('upper limit')

    def test_epicssignal_readwrite(self):
        epics.PV = FakeEpicsPV

        signal = EpicsSignal('readpv', write_pv='writepv')
        signal.wait_for_connection()

        self.assertEquals(signal.setpoint_pvname, 'writepv')
        self.assertEquals(signal.pvname, 'readpv')
        signal.value

        signal._update_rate = 2
        time.sleep(0.2)

        value = 10
        signal.value = value
        signal.setpoint = value
        self.assertEquals(signal.setpoint, value)
        signal.setpoint_ts

        signal.limits
        signal.precision
        signal.timestamp

        signal.read()
        signal.describe()
        signal.read_configuration()
        signal.describe_configuration()

        eval(repr(signal))
        time.sleep(0.2)

    def test_epicssignal_waveform(self):
        epics.PV = FakeEpicsWaveform

        def update_cb(value=None, **kwargs):
            self.assertIn(value, FakeEpicsWaveform.strings)

        signal = EpicsSignal('readpv', string=True)
        signal.wait_for_connection()

        signal.subscribe(update_cb)
        self.assertIn(signal.value, FakeEpicsWaveform.strings)

    def test_no_connection(self):
        epics.PV = FakeEpicsPV
        # special case in FakeEpicsPV that returns false in wait_for_connection
        sig = EpicsSignal('does_not_connect')
        self.assertRaises(TimeoutError, sig.wait_for_connection)

        sig = EpicsSignal('does_not_connect')
        self.assertRaises(TimeoutError, sig.put, 0.0)
        self.assertRaises(TimeoutError, sig.get)

        sig = EpicsSignal('connects', write_pv='does_not_connect')
        self.assertRaises(TimeoutError, sig.wait_for_connection)

    def test_enum_strs(self):
        epics.PV = FakeEpicsPV
        sig = EpicsSignal('connects')
        sig.wait_for_connection()

        enums = ['enum_strs']

        # hack this onto the FakeEpicsPV
        sig._read_pv.enum_strs = enums

        self.assertEquals(sig.enum_strs, enums)

    def test_setpoint(self):
        epics.PV = FakeEpicsPV
        sig = EpicsSignal('connects')
        sig.wait_for_connection()

        sig.get_setpoint()
        sig.get_setpoint(as_string=True)

    def test_epicssignalro(self):
        # not in initializer parameters anymore
        self.assertRaises(TypeError, EpicsSignalRO, 'test',
                          write_pv='nope_sorry')

    def test_describe(self):
        epics.PV = FakeEpicsPV
        sig = EpicsSignal('my_pv')
        sig._write_pv.enum_strs = ('enum1', 'enum2')
        sig.wait_for_connection()

        sig.put(1)
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'integer')
        self.assertEquals(desc['shape'], [])
        self.assertIn('precision', desc)
        self.assertIn('enum_strs', desc)
        self.assertIn('upper_ctrl_limit', desc)
        self.assertIn('lower_ctrl_limit', desc)

        sig.put('foo')
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'string')
        self.assertEquals(desc['shape'], [])

        sig.put(3.14)
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'number')
        self.assertEquals(desc['shape'], [])

        import numpy as np
        sig.put(np.array([1,]))
        desc = sig.describe()['my_pv']
        self.assertEquals(desc['dtype'], 'array')
        self.assertEquals(desc['shape'], [1,])

from . import main
is_main = (__name__ == '__main__')
main(is_main)
<|endoftext|>


<commit_before>"""
future: clean single-source support for Python 3 and 2
======================================================

The ``future`` module helps run Python 3.x-compatible code under Python 2
with minimal code cruft.

The goal is to allow you to write clean, modern, forward-compatible
Python 3 code today and to run it with minimal effort under Python 2
alongside a Python 2 stack that may contain dependencies that have not
yet been ported to Python 3.

It is designed to be used as follows::

    from __future__ import (absolute_import, division,
                            print_function, unicode_literals)
    from future import standard_library
    from future.builtins import *

followed by clean Python 3 code (with a few restrictions) that can run
unchanged on Python 2.7.

On Python 3, the import lines have zero effect (and zero namespace
pollution).

On Python 2, ``from future import standard_library`` installs
import hooks to allow renamed and moved standard library modules to be
imported from their new Py3 locations.

On Python 2, the ``from future.builtins import *`` line shadows builtins
to provide their Python 3 semantics. (See below for the explicit import
form.)

Documentation
-------------

See: http://python-future.org

Also see the docstrings for each of these modules for more info::

- future.standard_library
- future.builtins
- future.utils

Automatic conversion
--------------------
An experimental script called ``futurize`` is included to aid in making
either Python 2 code or Python 3 code compatible with both platforms
using the ``future`` module. See `<http://python-future.org/automatic_conversion.html>`_.

Credits
-------

:Author:  Ed Schofield
:Sponsor: Python Charmers Pty Ltd, Australia, and Python Charmers Pte
          Ltd, Singapore. http://pythoncharmers.com
:Others:  - The backported ``super()`` and ``range()`` functions are
            derived from Ryan Kelly's ``magicsuper`` module and Dan
            Crosta's ``xrange`` module.
          - The ``futurize`` script uses ``lib2to3``, ``lib3to2``, and
            parts of Armin Ronacher's ``python-modernize`` code.
          - The ``python_2_unicode_compatible`` decorator is from
            Django. The ``implements_iterator`` and ``with_metaclass``
            decorators are from Jinja2.
          - ``future`` incorporates the ``six`` module by Benjamin
            Peterson as ``future.utils.six``.
          - Documentation is generated using ``sphinx`` using an
            adaptation of Armin Ronacher's stylesheets from Jinja2.

Licensing
---------
Copyright 2013 Python Charmers Pty Ltd, Australia.
The software is distributed under an MIT licence. See LICENSE.txt.

"""

# No namespace pollution
__all__ = []

__ver_major__ = 0
__ver_minor__ = 8
__ver_patch__ = 0
__ver_sub__ = ''
__version__ = "%d.%d.%d%s" % (__ver_major__, __ver_minor__,
                              __ver_patch__, __ver_sub__)

<commit_msg>Bump version to v0.8.1-dev<commit_after>"""
future: clean single-source support for Python 3 and 2
======================================================

The ``future`` module helps run Python 3.x-compatible code under Python 2
with minimal code cruft.

The goal is to allow you to write clean, modern, forward-compatible
Python 3 code today and to run it with minimal effort under Python 2
alongside a Python 2 stack that may contain dependencies that have not
yet been ported to Python 3.

It is designed to be used as follows::

    from __future__ import (absolute_import, division,
                            print_function, unicode_literals)
    from future import standard_library
    from future.builtins import *

followed by clean Python 3 code (with a few restrictions) that can run
unchanged on Python 2.7.

On Python 3, the import lines have zero effect (and zero namespace
pollution).

On Python 2, ``from future import standard_library`` installs
import hooks to allow renamed and moved standard library modules to be
imported from their new Py3 locations.

On Python 2, the ``from future.builtins import *`` line shadows builtins
to provide their Python 3 semantics. (See below for the explicit import
form.)

Documentation
-------------

See: http://python-future.org

Also see the docstrings for each of these modules for more info::

- future.standard_library
- future.builtins
- future.utils

Automatic conversion
--------------------
An experimental script called ``futurize`` is included to aid in making
either Python 2 code or Python 3 code compatible with both platforms
using the ``future`` module. See `<http://python-future.org/automatic_conversion.html>`_.

Credits
-------

:Author:  Ed Schofield
:Sponsor: Python Charmers Pty Ltd, Australia, and Python Charmers Pte
          Ltd, Singapore. http://pythoncharmers.com
:Others:  - The backported ``super()`` and ``range()`` functions are
            derived from Ryan Kelly's ``magicsuper`` module and Dan
            Crosta's ``xrange`` module.
          - The ``futurize`` script uses ``lib2to3``, ``lib3to2``, and
            parts of Armin Ronacher's ``python-modernize`` code.
          - The ``python_2_unicode_compatible`` decorator is from
            Django. The ``implements_iterator`` and ``with_metaclass``
            decorators are from Jinja2.
          - ``future`` incorporates the ``six`` module by Benjamin
            Peterson as ``future.utils.six``.
          - Documentation is generated using ``sphinx`` using an
            adaptation of Armin Ronacher's stylesheets from Jinja2.

Licensing
---------
Copyright 2013 Python Charmers Pty Ltd, Australia.
The software is distributed under an MIT licence. See LICENSE.txt.

"""

# No namespace pollution
__all__ = []

__ver_major__ = 0
__ver_minor__ = 8
__ver_patch__ = 1
__ver_sub__ = '-dev'
__version__ = "%d.%d.%d%s" % (__ver_major__, __ver_minor__,
                              __ver_patch__, __ver_sub__)

<|endoftext|>


<commit_before>from nbconvert import ConverterRST, main
import nose.tools as nt

import os
import glob
from IPython.nbformat import current as nbformat

fname = 'tests/test.ipynb'
out_fname = 'tests/test.rst'

def clean_dir():
    "Remove .rst files created during conversion"
    map(os.remove, glob.glob("./tests/*.rst"))
    map(os.remove, glob.glob("./tests/*.png"))
    map(os.remove, glob.glob("./tests/*.html"))
    map(os.remove, glob.glob("./tests/test_files/*"))

@nt.with_setup(clean_dir, clean_dir)
def test_simple():
    c = ConverterRST(fname)
    f = c.render()
    nt.assert_true('rst' in f, 'changed file extension to rst')

@nt.with_setup(clean_dir, clean_dir)
def test_main():
    """
    Test main entry point
    """
    main(fname)
    nt.assert_true(os.path.exists(out_fname))

def test_render_heading():
    """ Unit test for cell type "heading" """
    # Generate and test heading cells level 1-6
    for level in xrange(1, 7):
        cell = {
            'cell_type': 'heading',
            'level'    : level,
            'source'   :  ['Test for heading type H{0}'.format(level)]
            }
        # Convert cell dictionaries to NotebookNode
        cell_nb = nbformat.NotebookNode(cell)
        # Make sure "source" attribute is uniconde not list.
        # For some reason, creating a NotebookNode manually like
        # this isn't converting source to a string like using
        # the create-from-file routine.
        if type(cell_nb.source) is list:
            cell_nb.source = '\n'.join(cell_nb.source)
        # Render to rst
        c = ConverterRST('')
        rst_list = c.render_heading(cell_nb)
        nt.assert_true(isinstance(rst_list, list))  # render should return a list
        rst_str = "".join(rst_list)
        # Confirm rst content
        chk_str = "Test for heading type H{0}\n{1}\n".format(
             level, c.heading_level[level] * 24)
        nt.assert_equal(rst_str, chk_str)

@nt.with_setup(clean_dir, clean_dir)
def test_main_html():
    """
    Test main entry point
    """
    main(fname, format='html')
    nt.assert_true(os.path.exists('tests/test.html'))
<commit_msg>Really check the file extension, not an arbitrary occurrence of 'rst'.<commit_after>from nbconvert import ConverterRST, main
import nose.tools as nt

import os
import glob
from IPython.nbformat import current as nbformat

fname = 'tests/test.ipynb'
out_fname = 'tests/test.rst'

def clean_dir():
    "Remove .rst files created during conversion"
    map(os.remove, glob.glob("./tests/*.rst"))
    map(os.remove, glob.glob("./tests/*.png"))
    map(os.remove, glob.glob("./tests/*.html"))
    map(os.remove, glob.glob("./tests/test_files/*"))

@nt.with_setup(clean_dir, clean_dir)
def test_simple():
    c = ConverterRST(fname)
    f = c.render()
    nt.assert_true(f.endswith('.rst'), 'changed file extension to rst')

@nt.with_setup(clean_dir, clean_dir)
def test_main():
    """
    Test main entry point
    """
    main(fname)
    nt.assert_true(os.path.exists(out_fname))

def test_render_heading():
    """ Unit test for cell type "heading" """
    # Generate and test heading cells level 1-6
    for level in xrange(1, 7):
        cell = {
            'cell_type': 'heading',
            'level'    : level,
            'source'   :  ['Test for heading type H{0}'.format(level)]
            }
        # Convert cell dictionaries to NotebookNode
        cell_nb = nbformat.NotebookNode(cell)
        # Make sure "source" attribute is uniconde not list.
        # For some reason, creating a NotebookNode manually like
        # this isn't converting source to a string like using
        # the create-from-file routine.
        if type(cell_nb.source) is list:
            cell_nb.source = '\n'.join(cell_nb.source)
        # Render to rst
        c = ConverterRST('')
        rst_list = c.render_heading(cell_nb)
        nt.assert_true(isinstance(rst_list, list))  # render should return a list
        rst_str = "".join(rst_list)
        # Confirm rst content
        chk_str = "Test for heading type H{0}\n{1}\n".format(
             level, c.heading_level[level] * 24)
        nt.assert_equal(rst_str, chk_str)

@nt.with_setup(clean_dir, clean_dir)
def test_main_html():
    """
    Test main entry point
    """
    main(fname, format='html')
    nt.assert_true(os.path.exists('tests/test.html'))
<|endoftext|>


<commit_before>#!/usr/bin/env python

# Lat Long - UTM, UTM - Lat Long conversions

from math import pi, sin, cos, tan, sqrt

# LatLong- UTM conversion..h
# definitions for lat/long to UTM and UTM to lat/lng conversions
# include <string.h>

_deg2rad = pi / 180.0
_rad2deg = 180.0 / pi

_EquatorialRadius = 2
_eccentricitySquared = 3

_ellipsoid = [
    # id, Ellipsoid name, Equatorial Radius, square of eccentricity
    # first once is a placeholder only, To allow array indices to match id
    # numbers
    [ -1, "Placeholder", 0, 0],
    [ 1, "Airy", 6377563, 0.00667054],
    [ 2, "Australian National", 6378160, 0.006694542],
    [ 3, "Bessel 1841", 6377397, 0.006674372],
    [ 4, "Bessel 1841 (Nambia] ", 6377484, 0.006674372],
    [ 5, "Clarke 1866", 6378206, 0.006768658],
    [ 6, "Clarke 1880", 6378249, 0.006803511],
    [ 7, "Everest", 6377276, 0.006637847],
    [ 8, "Fischer 1960 (Mercury] ", 6378166, 0.006693422],
    [ 9, "Fischer 1968", 6378150, 0.006693422],
    [ 10, "GRS 1967", 6378160, 0.006694605],
    [ 11, "GRS 1980", 6378137, 0.00669438],
    [ 12, "Helmert 1906", 6378200, 0.006693422],
    [ 13, "Hough", 6378270, 0.00672267],
    [ 14, "International", 6378388, 0.00672267],
    [ 15, "Krassovsky", 6378245, 0.006693422],
    [ 16, "Modified Airy", 6377340, 0.00667054],
    [ 17, "Modified Everest", 6377304, 0.006637847],
    [ 18, "Modified Fischer 1960", 6378155, 0.006693422],
    [ 19, "South American 1969", 6378160, 0.006694542],
    [ 20, "WGS 60", 6378165, 0.006693422],
    [ 21, "WGS 66", 6378145, 0.006694542],
    [ 22, "WGS-72", 6378135, 0.006694318],
    [ 23, "WGS-84", 6378137, 0.00669438]
]

# Reference ellipsoids derived from Peter H. Dana's website:
# http://www.utexas.edu/depts/grg/gcraft/notes/datum/elist.html
# Department of Geography,
# University of Texas at Austin
# Email: pdana@mail.utexas.edu
# 3/22/95

# Source:
# Defense Mapping Agency. 1987b. DMA Technical Report: Supplement to Department
# of Defense World Geodetic System 1984 Technical Report. Part I and II.
# Washington, DC: Defense Mapping Agency

# def LLtoUTM(int ReferenceEllipsoid, const double Lat, const double Long,
#            double &UTMNorthing, double &UTMEasting, char* UTMZone)

def LLtoUTM(ReferenceEllipsoid, Lat, Long, ZoneNumber=False):
    # Converts lat/long to UTM coords. Equations from USGS Bulletin 1532

    # East Longitudes are positive, West longitudes are negative.
    # North latitudes are positive, South latitudes are negative
    # Lat and Long are in decimal degrees
    # Written by Chuck Gantz- chuck.gantz@globalstar.com

    a = _ellipsoid[ReferenceEllipsoid][_EquatorialRadius]
    eccSquared = _ellipsoid[ReferenceEllipsoid][_eccentricitySquared]
    k0 = 0.9996

    # Make sure the longitude is between -180.00 .. 179.9
    LongTemp = (Long+180)-int((Long+180)/360)*360-180 # -180.00 .. 179.9

    LatRad = Lat*_deg2rad
    LongRad = LongTemp*_deg2rad

    ZoneNumber = int((LongTemp + 180)/6) + 1

    if Lat >= 56.0 and Lat < 64.0 and LongTemp >= 3.0 and LongTemp < 12.0:
        ZoneNumber = 32

    # Special zones for Svalbard
    if Lat >= 72.0 and Lat < 84.0:
        if LongTemp >= 0.0  and LongTemp <  9.0: ZoneNumber = 31
        elif LongTemp >= 9.0  and LongTemp < 21.0: ZoneNumber = 33
        elif LongTemp >= 21.0 and LongTemp < 33.0: ZoneNumber = 35
        elif LongTemp >= 33.0 and LongTemp < 42.0: ZoneNumber = 37

    LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3 # +3 puts origin in middle of zone
    LongOriginRad = LongOrigin * _deg2rad

    # Compute the UTM Zone from the latitude and longitude
    UTMZone = "%d%c" % (ZoneNumber, _UTMLetterDesignator(Lat))

    eccPrimeSquared = (eccSquared)/(1-eccSquared)
    N = a/sqrt(1-eccSquared*sin(LatRad)*sin(LatRad))
    T = tan(LatRad)*tan(LatRad)
    C = eccPrimeSquared*cos(LatRad)*cos(LatRad)
    A = cos(LatRad)*(LongRad-LongOriginRad)

    M = a*((1
            - eccSquared/4
            - 3*eccSquared*eccSquared/64
            - 5*eccSquared*eccSquared*eccSquared/256)*LatRad
           - (3*eccSquared/8
              + 3*eccSquared*eccSquared/32
              + 45*eccSquared*eccSquared*eccSquared/1024)*sin(2*LatRad)
           + (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(4*LatRad)
           - (35*eccSquared*eccSquared*eccSquared/3072)*sin(6*LatRad))

    UTMEasting = (k0*N*(A+(1-T+C)*A*A*A/6
                        + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120)
                  + 500000.0)

    UTMNorthing = (k0*(M+N*tan(LatRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
                                        + (61
                                           -58*T
                                           +T*T
                                           +600*C
                                           -330*eccPrimeSquared)*A*A*A*A*A*A/720)))

    if Lat < 0:
        UTMNorthing = UTMNorthing + 10000000.0; #10000000 meter offset for southern hemisphere
    return (UTMZone, UTMEasting, UTMNorthing)

def _UTMLetterDesignator(Lat):
    # This routine determines the correct UTM letter designator for the given
    # latitude. Returns 'Z' if latitude is outside the UTM limits of 84N to 80S
    # Written by Chuck Gantz: chuck.gantz@globalstar.com

    if 84 >= Lat >= 72: return 'X'
    elif 72 > Lat >= 64: return 'W'
    elif 64 > Lat >= 56: return 'V'
    elif 56 > Lat >= 48: return 'U'
    elif 48 > Lat >= 40: return 'T'
    elif 40 > Lat >= 32: return 'S'
    elif 32 > Lat >= 24: return 'R'
    elif 24 > Lat >= 16: return 'Q'
    elif 16 > Lat >= 8: return 'P'
    elif  8 > Lat >= 0: return 'N'
    elif  0 > Lat >= -8: return 'M'
    elif -8> Lat >= -16: return 'L'
    elif -16 > Lat >= -24: return 'K'
    elif -24 > Lat >= -32: return 'J'
    elif -32 > Lat >= -40: return 'H'
    elif -40 > Lat >= -48: return 'G'
    elif -48 > Lat >= -56: return 'F'
    elif -56 > Lat >= -64: return 'E'
    elif -64 > Lat >= -72: return 'D'
    elif -72 > Lat >= -80: return 'C'
    else: return 'Z'    # if the Latitude is outside the UTM limits

    # void UTMtoLL(int ReferenceEllipsoid, const double UTMNorthing,
    #             const double UTMEasting, const char* UTMZone,
    #             double& Lat,  double& Long )

def UTMtoLL(ReferenceEllipsoid, northing, easting, zone):
    # Converts UTM coords to lat/long. Equations from USGS Bulletin 1532

    # East Longitudes are positive, West longitudes are negative. North latitudes
    # are positive, South latitudes are negative. Lat and Long are in decimal
    # degrees.
    # Written by Chuck Gantz: chuck.gantz@globalstar.com.
    # Converted to Python by Russ Nelson <nelson@crynwr.com>

    k0 = 0.9996
    a = _ellipsoid[ReferenceEllipsoid][_EquatorialRadius]
    eccSquared = _ellipsoid[ReferenceEllipsoid][_eccentricitySquared]
    e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared))
    # NorthernHemisphere; //1 for northern hemisphere, 0 for southern

    x = easting - 500000.0 # remove 500,000 meter offset for longitude
    y = northing

    ZoneLetter = zone[-1]
    ZoneNumber = int(zone[:-1])
    if ZoneLetter >= 'N':
        NorthernHemisphere = 1  # point is in northern hemisphere
    else:
        NorthernHemisphere = 0  # point is in southern hemisphere
        y -= 10000000.0         # remove 10,000,000 meter offset used for southern hemisphere

    LongOrigin = (ZoneNumber - 1)*6 - 180 + 3  # +3 puts origin in middle of zone

    eccPrimeSquared = (eccSquared)/(1-eccSquared)

    M = y / k0
    mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256))

    phi1Rad = (mu + (3*e1/2-27*e1*e1*e1/32)*sin(2*mu)
               + (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu)
               +(151*e1*e1*e1/96)*sin(6*mu))
    phi1 = phi1Rad*_rad2deg;

    N1 = a/sqrt(1-eccSquared*sin(phi1Rad)*sin(phi1Rad))
    T1 = tan(phi1Rad)*tan(phi1Rad)
    C1 = eccPrimeSquared*cos(phi1Rad)*cos(phi1Rad)
    R1 = a*(1-eccSquared)/pow(1-eccSquared*sin(phi1Rad)*sin(phi1Rad), 1.5)
    D = x/(N1*k0)

    Lat = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
                                          +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720)
    Lat = Lat * _rad2deg

    Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
            *D*D*D*D*D/120)/cos(phi1Rad)
    Long = LongOrigin + Long * _rad2deg
    return (Lat, Long)

if __name__ == '__main__':
    #inLat, inLong = 40 + (6 + 18.3591/60)/60, -(88 + (13 + 9.52349/60)/60)
    inLat, inLong = 50, -10
    (z, e, n) = LLtoUTM(23, inLat, inLong)
    outLat, outLong = UTMtoLL(23, n, e, z)

    print "Input (lat/long): {}, {}\nOutput (lat/long): {} {}".format(inLat, inLong, outLat, outLong)
    print "Intermediate UTM: {}, {}, {}".format(e, n, z)
<commit_msg>Add support for NumPy arrays in the conversion. This speeds up the conversion of lots of data by omitting the need for multiple calls to UTMtoLL or LLtoUTM.<commit_after>#!/usr/bin/env python

# Lat Long - UTM, UTM - Lat Long conversions

# Adjusted for use with NumPy by Pierre Cazenave <pica {at} pml.ac.uk>

import numpy as np

# LatLong- UTM conversion..h
# definitions for lat/long to UTM and UTM to lat/lng conversions
# include <string.h>

_EquatorialRadius = 2
_eccentricitySquared = 3

_ellipsoid = [
    # id, Ellipsoid name, Equatorial Radius, square of eccentricity
    # first once is a placeholder only, To allow array indices to match id
    # numbers
    [ -1, "Placeholder", 0, 0],
    [ 1, "Airy", 6377563, 0.00667054],
    [ 2, "Australian National", 6378160, 0.006694542],
    [ 3, "Bessel 1841", 6377397, 0.006674372],
    [ 4, "Bessel 1841 (Nambia] ", 6377484, 0.006674372],
    [ 5, "Clarke 1866", 6378206, 0.006768658],
    [ 6, "Clarke 1880", 6378249, 0.006803511],
    [ 7, "Everest", 6377276, 0.006637847],
    [ 8, "Fischer 1960 (Mercury] ", 6378166, 0.006693422],
    [ 9, "Fischer 1968", 6378150, 0.006693422],
    [ 10, "GRS 1967", 6378160, 0.006694605],
    [ 11, "GRS 1980", 6378137, 0.00669438],
    [ 12, "Helmert 1906", 6378200, 0.006693422],
    [ 13, "Hough", 6378270, 0.00672267],
    [ 14, "International", 6378388, 0.00672267],
    [ 15, "Krassovsky", 6378245, 0.006693422],
    [ 16, "Modified Airy", 6377340, 0.00667054],
    [ 17, "Modified Everest", 6377304, 0.006637847],
    [ 18, "Modified Fischer 1960", 6378155, 0.006693422],
    [ 19, "South American 1969", 6378160, 0.006694542],
    [ 20, "WGS 60", 6378165, 0.006693422],
    [ 21, "WGS 66", 6378145, 0.006694542],
    [ 22, "WGS-72", 6378135, 0.006694318],
    [ 23, "WGS-84", 6378137, 0.00669438]
]

# Reference ellipsoids derived from Peter H. Dana's website:
# http://www.utexas.edu/depts/grg/gcraft/notes/datum/elist.html
# Department of Geography,
# University of Texas at Austin
# Email: pdana@mail.utexas.edu
# 3/22/95

# Source:
# Defense Mapping Agency. 1987b. DMA Technical Report: Supplement to Department
# of Defense World Geodetic System 1984 Technical Report. Part I and II.
# Washington, DC: Defense Mapping Agency

# def LLtoUTM(int ReferenceEllipsoid, const double Lat, const double Long,
#            double &UTMNorthing, double &UTMEasting, char* UTMZone)

def LLtoUTM(ReferenceEllipsoid, Lat, Long, ZoneNumber=False):
    # Converts lat/long to UTM coords. Equations from USGS Bulletin 1532

    # East Longitudes are positive, West longitudes are negative.
    # North latitudes are positive, South latitudes are negative
    # Lat and Long are in decimal degrees
    # Written by Chuck Gantz- chuck.gantz@globalstar.com

    if ~isinstance(Long, np.ndarray):
        Long = np.asarray(Long)

    if ~isinstance(Lat, np.ndarray):
        Lat = np.asarray(Lat)

    a = _ellipsoid[ReferenceEllipsoid][_EquatorialRadius]
    eccSquared = _ellipsoid[ReferenceEllipsoid][_eccentricitySquared]
    k0 = 0.9996

    # Make sure the longitude is between -180.00 .. 179.9
    LongTemp = (Long+180)-np.floor((Long+180)/360).astype(int)*360-180 # -180.00 .. 179.9

    LatRad = np.deg2rad(Lat)
    LongRad = np.deg2rad(LongTemp)

    # Add loop around the Latitudes to get the correct zone information. Build
    # a list of the zones for all coordinates.
    Zone = []
    if np.ndim(Lat) > 0:
        for c, ll in enumerate(zip(LongTemp, Lat)):
            ZoneNumber = int((ll[0] + 180)/6) + 1

            if ll[1] >= 56.0 and ll[1] < 64.0 and ll[0] >= 3.0 and ll[0] < 12.0:
                ZoneNumber = 32

            # Special zones for Svalbard
            if ll[1] >= 72.0 and ll[1] < 84.0:
                if ll[0] >= 0.0  and ll[0] <  9.0: ZoneNumber = 31
                elif ll[0] >= 9.0  and ll[0] < 21.0: ZoneNumber = 33
                elif ll[0] >= 21.0 and ll[0] < 33.0: ZoneNumber = 35
                elif ll[0] >= 33.0 and ll[0] < 42.0: ZoneNumber = 37

            LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3 # +3 puts origin in middle of zone
            LongOriginRad = np.deg2rad(LongOrigin)

            # Compute the UTM Zone from the latitude and longitude
            UTMZone ="%d%c" % (ZoneNumber, _UTMLetterDesignator(ll[1]))

            Zone.append(UTMZone)

    eccPrimeSquared = (eccSquared)/(1-eccSquared)
    N = a/np.sqrt(1-eccSquared*np.sin(LatRad)*np.sin(LatRad))
    T = np.tan(LatRad)*np.tan(LatRad)
    C = eccPrimeSquared*np.cos(LatRad)*np.cos(LatRad)
    A = np.cos(LatRad)*(LongRad-LongOriginRad)

    M = a*((1
            - eccSquared/4
            - 3*eccSquared*eccSquared/64
            - 5*eccSquared*eccSquared*eccSquared/256)*LatRad
           - (3*eccSquared/8
              + 3*eccSquared*eccSquared/32
              + 45*eccSquared*eccSquared*eccSquared/1024)*np.sin(2*LatRad)
           + (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*np.sin(4*LatRad)
           - (35*eccSquared*eccSquared*eccSquared/3072)*np.sin(6*LatRad))

    UTMEasting = (k0*N*(A+(1-T+C)*A*A*A/6
                        + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120)
                  + 500000.0)

    UTMNorthing = (k0*(M+N*np.tan(LatRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
                                        + (61
                                           -58*T
                                           +T*T
                                           +600*C
                                           -330*eccPrimeSquared)*A*A*A*A*A*A/720)))

    Northing = []
    if np.ndim(Lat) > 0:
        for c, l in enumerate(Lat):
            if l < 0:
                Northing.append(UTMNorthing[c] + 10000000.0) # 10000000 meter offset for southern hemisphere
            else:
                Northing.append(UTMNorthing[c])

        UTMNorthing = Northing
    else:
        if Lat < 0:
            UTMNorthing = UTMNorthing + 10000000.0; #10000000 meter offset for southern hemisphere

    return (Zone, UTMEasting, UTMNorthing)

def _UTMLetterDesignator(Lat):
    # This routine determines the correct UTM letter designator for the given
    # latitude. Returns 'Z' if latitude is outside the UTM limits of 84N to 80S
    # Written by Chuck Gantz: chuck.gantz@globalstar.com

    if 84 >= Lat >= 72: return 'X'
    elif 72 > Lat >= 64: return 'W'
    elif 64 > Lat >= 56: return 'V'
    elif 56 > Lat >= 48: return 'U'
    elif 48 > Lat >= 40: return 'T'
    elif 40 > Lat >= 32: return 'S'
    elif 32 > Lat >= 24: return 'R'
    elif 24 > Lat >= 16: return 'Q'
    elif 16 > Lat >= 8: return 'P'
    elif  8 > Lat >= 0: return 'N'
    elif  0 > Lat >= -8: return 'M'
    elif -8> Lat >= -16: return 'L'
    elif -16 > Lat >= -24: return 'K'
    elif -24 > Lat >= -32: return 'J'
    elif -32 > Lat >= -40: return 'H'
    elif -40 > Lat >= -48: return 'G'
    elif -48 > Lat >= -56: return 'F'
    elif -56 > Lat >= -64: return 'E'
    elif -64 > Lat >= -72: return 'D'
    elif -72 > Lat >= -80: return 'C'
    else: return 'Z'    # if the Latitude is outside the UTM limits

    # void UTMtoLL(int ReferenceEllipsoid, const double UTMNorthing,
    #             const double UTMEasting, const char* UTMZone,
    #             double& Lat,  double& Long )

def UTMtoLL(ReferenceEllipsoid, northing, easting, zone):
    # Converts UTM coords to lat/long. Equations from USGS Bulletin 1532

    # East Longitudes are positive, West longitudes are negative. North latitudes
    # are positive, South latitudes are negative. Lat and Long are in decimal
    # degrees.
    # Written by Chuck Gantz: chuck.gantz@globalstar.com.
    # Converted to Python by Russ Nelson <nelson@crynwr.com>

    k0 = 0.9996
    a = _ellipsoid[ReferenceEllipsoid][_EquatorialRadius]
    eccSquared = _ellipsoid[ReferenceEllipsoid][_eccentricitySquared]
    e1 = (1-np.sqrt(1-eccSquared))/(1+np.sqrt(1-eccSquared))
    # NorthernHemisphere; //1 for northern hemisphere, 0 for southern

    if ~isinstance(easting, np.ndarray):
        easting = np.asarray(easting)

    if ~isinstance(northing, np.ndarray):
        northing = np.asarray(northing)

    x = easting - 500000.0 # remove 500,000 meter offset for longitude
    y = northing

    ZoneLetter = zone[-1]
    ZoneNumber = int(zone[:-1])
    if ZoneLetter >= 'N':
        NorthernHemisphere = 1  # point is in northern hemisphere
    else:
        NorthernHemisphere = 0  # point is in southern hemisphere
        y -= 10000000.0         # remove 10,000,000 meter offset used for southern hemisphere

    LongOrigin = (ZoneNumber - 1)*6 - 180 + 3  # +3 puts origin in middle of zone

    eccPrimeSquared = (eccSquared)/(1-eccSquared)

    M = y / k0
    mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256))

    phi1Rad = (mu + (3*e1/2-27*e1*e1*e1/32)*np.sin(2*mu)
               + (21*e1*e1/16-55*e1*e1*e1*e1/32)*np.sin(4*mu)
               +(151*e1*e1*e1/96)*np.sin(6*mu))
    phi1 = np.rad2deg(phi1Rad)

    N1 = a/np.sqrt(1-eccSquared*np.sin(phi1Rad)*np.sin(phi1Rad))
    T1 = np.tan(phi1Rad)*np.tan(phi1Rad)
    C1 = eccPrimeSquared*np.cos(phi1Rad)*np.cos(phi1Rad)
    R1 = a*(1-eccSquared)/np.power(1-eccSquared*np.sin(phi1Rad)*np.sin(phi1Rad), 1.5)
    D = x/(N1*k0)

    Lat = phi1Rad - (N1*np.tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
                                          +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720)
    Lat = np.rad2deg(Lat)

    Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
            *D*D*D*D*D/120)/np.cos(phi1Rad)
    Long = LongOrigin + np.rad2deg(Long)
    return (Lat, Long)

if __name__ == '__main__':
    #inLat, inLong = 40 + (6 + 18.3591/60)/60, -(88 + (13 + 9.52349/60)/60)
    inLat, inLong = 50, -10
    (z, e, n) = LLtoUTM(23, inLat, inLong)
    outLat, outLong = UTMtoLL(23, n, e, z)

    print "Input (lat/long): {}, {}\nOutput (lat/long): {} {}".format(inLat, inLong, outLat, outLong)
    print "Intermediate UTM: {}, {}, {}".format(e, n, z)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import division

from odelab.scheme.rungekutta import *
from odelab.scheme.generallinear import *
from odelab.scheme import *
from odelab.scheme.classic import *
from odelab.scheme.exponential import *

from odelab.store import Store, PyTableStore, SimpleStore

from odelab.system.classic import *
from odelab.system.exponential import *
from odelab import *

import tempfile
import os

import numpy as np
import numpy.testing as npt
import unittest
import pytest

import matplotlib.pyplot as plt

Solver.catch_runtime = False

def f(t,u):
	return t*np.ones_like(u)

def const_f(c,t,u):
	return c*np.ones_like(u)

def time_f(t,u):
	return t

class TestMisc(unittest.TestCase):
	def test_solver_autosave(self):
		solver = Solver(ExplicitEuler(h=.1), System(f))
		solver.initialize(u0=1.)
		solver.run()
		self.assertEqual(solver.guess_name(), 'System_ExplicitEuler_T1.0')

	def test_duration(self):
		"""Duration are added from run to run"""
		solver = Solver(ExplicitEuler(h=.1), System(f))
		solver.initialize(u0=1.,time=1.,)
		solver.run()
		d1 = solver.store['duration']
		solver.run(time=.1)
		d2 = solver.store['duration']
		self.assertGreater(d2, d1)

class InitializedTwiceError(ValueError):
	pass

class Scheme_init_once(ExplicitEuler):
	def __init__(self, *args,**kwargs):
		super(Scheme_init_once,self).__init__(*args, **kwargs)
		self.is_initialized = False

	def initialize(self, events):
		if self.is_initialized:
			raise InitializedTwiceError('initialized twice!')
		super(Scheme_init_once,self).initialize(events)
		self.is_initialized = True

class TestInitialize(unittest.TestCase):
	def test_initialize_len1(self):
		solver = Solver(ExplicitEuler(.1),System(f))
		solver.initialize(u0=1.)
		self.assertEqual(len(solver),1)

	def test_start_from_two(self):
		# check that a scheme is not initialized twice, even if we start from more than one event
		dt = .1
		solver = Solver(Scheme_init_once(dt), System(f))
		solver.initialize(u0=1.)
		solver.run(2*dt)
		self.assertEqual(len(solver),3)
		solver.scheme.is_initialized = False
		solver.run(1.)
		print(len(solver))
		print(solver.get_events())

	def test_initialize_reset_scheme(self):
		solver = Solver(Scheme_init_once(.1), System(f))
		solver.initialize(u0=1., name='first')
		self.assertIs(solver.current_scheme, None)
		solver.run(1.)
		solver.initialize(u0=2.,name='second')
		with self.assertRaises(InitializedTwiceError):
			solver.run(1.)

	def test_multistep_init_exception(self):
		multi_scheme = AdamsBashforth2(.1)
		s = Solver(scheme=multi_scheme, system=System(f))
		s.initialize(u0=1.)
		with self.assertRaises(MultistepInitializationError):
			with s.open_store() as events:
				s.set_scheme(multi_scheme, events)

class Test_Access(unittest.TestCase):
	"""
	Test the Solver.get_events method.
	"""
	def setUp(self):
		self.s = Solver(ExplicitEuler(.1), System(partial(const_f, 1.)))
		self.time = 30
		self.s.initialize(u0=np.array([0.]),time=self.time)

	def test_access(self):
		self.s.run()
		sampling_rate = .5
		time = 15
		evts = self.s.get_events(t0=0, time=time, sampling_rate=sampling_rate)
		npt.assert_almost_equal(len(evts.T), len(self.s)*sampling_rate/2, -1) # approx 1/4 of total nb of events
		## self.assertEqual(len(evts.T), 250)
		npt.assert_array_almost_equal(evts[:,-1], np.array([time, time]))

	def test_notrun(self):
		with self.assertRaises(Solver.NotRun):
			self.s.get_events()

from functools import partial
const_r = partial(const_f, 1.)
const_c = partial(const_f, 1.j)

class Harness_Solver(object):
	def setUp(self):
		self.setup_solver()

	dim = 1
	def set_system(self, f):
		self.solver.system = System(f)

	def test_scheme_str(self):
		# should not raise an exception even though h is not yet set in the underlying scheme:
		print(str(self.solver))

	def test_initialize(self):
		u0 = np.random.rand(self.dim)
		self.solver.initialize(u0=u0,)
		self.assertEqual(self.solver.time, Solver.time)
		self.assertEqual(len(self.solver), 1)

	def test_initialize_twice(self):
		if isinstance(self.solver.store, SimpleStore):
			pytest.skip()
		u0 = np.random.rand(self.dim)
		self.solver.initialize(u0=u0)
		with self.assertRaises(PyTableStore.AlreadyInitialized):
			self.solver.initialize(u0=u0)

	@pytest.mark.skip('Not relevant anymore, time step is initialized directly at the scheme level')
	def test_initialize_scheme(self):
		h = 10.
		self.solver.initialize(u0=np.random.rand(self.dim),)
		e0 = self.solver.initial()
		with self.solver.open_store() as events:
			self.solver.set_scheme(self.solver.scheme, events)
		self.solver.step(e0[-1], e0[:-1],)
		self.assertEqual(self.solver.scheme.h, h)

	def test_quadratic(self):
		print(type(self).__name__)
		self.set_system(time_f)
		self.solver.initialize(u0=1., time=1.,)
		self.solver.run()
		# u'(t) = t; u(0) = u0; => u(t) == u0 + t**2/2
		npt.assert_array_almost_equal(self.solver.final(), np.array([3/2,1.]), decimal=1)

	def check_const(self, f, u0, expected):
		"""should solve the f=c exactly"""
		print(type(self).__name__)
		self.check_skip(u0,f)
		self.set_system(f)
		self.solver.initialize(u0=u0, time=1.,)
		self.solver.run()
		expected_event = np.hstack([expected, 1.])
		npt.assert_almost_equal(self.solver.final(), expected_event, 1)

	def check_skip(self,u0,f):
		return

	def test_real_const(self):
		self.check_const(const_r, 1., 2.)

	@pytest.mark.skip('Current nonlinear solver does not work with the complex type.')
	def test_complex_const(self):
		self.check_const(const_c, 1.+0j, 1.+1.j)

	def test_repr(self):
		expected = '<Solver: {0}'.format(repr(self.solver.scheme))
		r = repr(self.solver)
		self.assertTrue(r.startswith(expected))
		if self.solver.init_scheme is not None:
			self.assertRegex(r, repr(self.solver.init_scheme))

class Test_EEuler(Harness_Solver, unittest.TestCase):
	def setup_solver(self):
		self.solver = Solver(ExplicitEuler(h=.1), System(f))

class Test_ETrapezoidal(Harness_Solver, unittest.TestCase):
	def setup_solver(self):
		self.solver = Solver(ExplicitTrapezoidal(h=.1), System(f))

class Test_RK4(Harness_Solver, unittest.TestCase):
	def setup_solver(self):
		self.solver = Solver(RungeKutta4(h=.1), System(f))

class Test_Midpoint(Harness_Solver, unittest.TestCase):
	def setup_solver(self):
		self.solver = Solver(ImplicitMidPoint(h=.1), System(f))

class Test_RK34(Harness_Solver, unittest.TestCase):
	def setup_solver(self):
		self.solver = Solver(RungeKutta34(h=.1), System(f))

class Test_AB(Harness_Solver, unittest.TestCase):
	def setup_solver(self):
		multi_scheme = AdamsBashforth2(.1)
		self.solver = Solver(multi_scheme, System(f), init_scheme=ExplicitEuler(h=.1))

class Harness_Solver_NoComplex(Harness_Solver):

	def check_skip(self,u0,f):
		if isinstance(u0,float) and f is const_c:
			raise SkipTest('Does not work with real initial conditions and complex vector fields')

class Test_ode15s(Harness_Solver_NoComplex, unittest.TestCase):
	def setup_solver(self):
		self.solver = Solver(ode15s(h=.1), System(f))

class Test_LawsonEuler(Harness_Solver_NoComplex, unittest.TestCase):
	def set_system(self, f):
		self.solver.system = NoLinear(f,self.dim)
	def setup_solver(self):
		self.solver = Solver(LawsonEuler(h=.1), NoLinear(f,self.dim))

class Test_IEuler(Harness_Solver, unittest.TestCase):
	def setup_solver(self):
		self.solver = Solver(ImplicitEuler(h=.1), System(f))

class Test_RK34Vdp(unittest.TestCase):
	def setUp(self):
		time = 7.8
		self.h_init = time/50
		self.scheme = RungeKutta34(h=self.h_init)
		self.s = Solver(self.scheme, VanderPol(mu=1.))
		self.s.initialize(u0 = array([.2,1]), time=time, )

	def test_run(self):
		self.s.run()
		self.assertLess(self.scheme.h, self.h_init)

class TestStability(unittest.TestCase):
	def test_unstable(self):
		with self.assertRaises(Solver.Unstable):
			s = Solver(LawsonEuler(h=10.), Linear(np.array([[1.e2]])))
			s.initialize(u0 = 1., time = 100,)
			s.run()

class DummyException(Exception):
	pass

class LimitedSys(System):
	def __init__(self, limit):
		self.limit = limit
		self.i = 0
	def f(self, t, x):
		if self.i < self.limit:
			self.i += 1
			return 0
		else:
			raise DummyException()

class Test_FinalTimeExceptions(unittest.TestCase):
	limit = 20
	def setUp(self):
		self.sys = LimitedSys(self.limit)
		self.scheme = ExplicitEuler(h=.1)
		self.s = Solver(self.scheme, self.sys)
		self.s.catch_runtime = True
		self.s.initialize(u0=0, time=10, )

	def test_final_time_not_reached(self):
		with self.assertRaises(Solver.FinalTimeNotReached):
			self.s.run(max_iter = 1)

	def test_max_iter(self):
		try:
			self.s.run()
		except self.s.RuntimeError:
			pass
		self.assertGreaterEqual(self.s._max_iter, self.s.max_iter_factor*self.s.time/self.scheme.h)
		time = 50
		try:
			self.s.run(50)
		except self.s.RuntimeError:
			pass
		self.assertGreaterEqual(self.s._max_iter, self.s.max_iter_factor*time/self.scheme.h)

	def test_sys_exception(self):
		with self.assertRaises(Solver.RuntimeError):
			self.s.run()

	def test_sys_no_runtime_exception(self):
		self.s.catch_runtime = False
		with self.assertRaises(DummyException):
			self.s.run()

def faulty_function(t,u):
	raise Exception('message')

class Test_Exceptions(unittest.TestCase):
	def setUp(self):
		self.s = Solver(ExplicitEuler(h=.1), Linear(np.array([[1]])))
	def test_no_u0(self):
		with self.assertRaises(Solver.NotInitialized):
			self.s.initialize()
	def test_no_initialize(self):
		with self.assertRaises(Solver.NotInitialized):
			self.s.run()
	def test_unstable(self):
		self.s = Solver(ExplicitEuler(h=.1), Linear(np.array([[float('inf')]])))
		self.s.initialize(u0=np.array([0]))
		with self.assertRaises(Solver.Unstable):
			self.s.run()
	def test_runtime_exception(self):
		self.s = Solver(ExplicitEuler(h=.1), System(faulty_function))
		self.s.catch_runtime = True
		self.s.initialize(u0=0)
		with self.assertRaises(Solver.RuntimeError):
			self.s.run()

class TotSys(System):
	def total(self, xt):
		return np.sum(xt[:-1],axis=0)

def minus_x(t, x):
	return -x

class Test_Simple(unittest.TestCase):
	def setUp(self):
		sys = TotSys(minus_x)
		self.s = Solver(ExplicitEuler(h=.1), sys)

	def test_time(self):
		sol = self.s
		sol.h = Solver.time/10
		sol.initialize(u0=0.)
		sol.run(sol.h)
		npt.assert_(sol.final_time() < Solver.time)

	def test_extra_run(self):
		"""test that an extra run continues from last time"""
		sol = self.s
		sol.initialize(u0=1.)
		sol.run()
		npt.assert_almost_equal(sol.final_time(),Solver.time)
		sol.run()
		npt.assert_almost_equal(sol.final_time(),2*Solver.time)

	def test_plot_args(self):
		self.s.initialize(u0=np.array([1.,1.,1.]))
		self.s.run()
		plt.clf()
		lines = self.s.plot(0,lw=5).axis.lines
		npt.assert_equal(len(lines),1)
		plt.clf()
		lines = self.s.plot(lw=5).axis.lines
		npt.assert_equal(len(lines),3)
		npt.assert_equal(lines[-1].get_linewidth(),5)

	def test_plot_function(self):
		self.s.initialize(u0=np.array([1.,1.,1.]))
		self.s.run()
		lines = self.s.plot_function('total', lw=4).axis.lines
		npt.assert_equal(lines[-1].get_linewidth(), 4)

<commit_msg>test_solver: cleanup<commit_after># -*- coding: utf-8 -*-
from __future__ import division

from odelab.scheme.rungekutta import *
from odelab.scheme.generallinear import *
from odelab.scheme import *
from odelab.scheme.classic import *
from odelab.scheme.exponential import *

from odelab.store import Store, PyTableStore, SimpleStore

from odelab.system.classic import *
from odelab.system.exponential import *
from odelab import *

import tempfile
import os

import numpy as np
import numpy.testing as npt
import unittest
import pytest

import matplotlib.pyplot as plt

Solver.catch_runtime = False

def f(t,u):
	return t*np.ones_like(u)

def const_f(c,t,u):
	return c*np.ones_like(u)

def time_f(t,u):
	return t

class TestMisc(unittest.TestCase):
	def test_solver_autosave(self):
		solver = Solver(ExplicitEuler(h=.1), System(f))
		solver.initialize(u0=1.)
		solver.run()
		self.assertEqual(solver.guess_name(), 'System_ExplicitEuler_T1.0')

	def test_duration(self):
		"""Duration are added from run to run"""
		solver = Solver(ExplicitEuler(h=.1), System(f))
		solver.initialize(u0=1.,time=1.,)
		solver.run()
		d1 = solver.store['duration']
		solver.run(time=.1)
		d2 = solver.store['duration']
		self.assertGreater(d2, d1)

class InitializedTwiceError(ValueError):
	pass

class Scheme_init_once(ExplicitEuler):
	def __init__(self, *args,**kwargs):
		super(Scheme_init_once,self).__init__(*args, **kwargs)
		self.is_initialized = False

	def initialize(self, events):
		if self.is_initialized:
			raise InitializedTwiceError('initialized twice!')
		super(Scheme_init_once,self).initialize(events)
		self.is_initialized = True

class TestInitialize(unittest.TestCase):
	def test_initialize_len1(self):
		solver = Solver(ExplicitEuler(.1),System(f))
		solver.initialize(u0=1.)
		self.assertEqual(len(solver),1)

	def test_start_from_two(self):
		# check that a scheme is not initialized twice, even if we start from more than one event
		dt = .1
		solver = Solver(Scheme_init_once(dt), System(f))
		solver.initialize(u0=1.)
		solver.run(2*dt)
		self.assertEqual(len(solver),3)
		solver.scheme.is_initialized = False
		solver.run(1.)
		print(len(solver))
		print(solver.get_events())

	def test_initialize_reset_scheme(self):
		solver = Solver(Scheme_init_once(.1), System(f))
		solver.initialize(u0=1., name='first')
		self.assertIs(solver.current_scheme, None)
		solver.run(1.)
		solver.initialize(u0=2.,name='second')
		with self.assertRaises(InitializedTwiceError):
			solver.run(1.)

	def test_multistep_init_exception(self):
		multi_scheme = AdamsBashforth2(.1)
		s = Solver(scheme=multi_scheme, system=System(f))
		s.initialize(u0=1.)
		with self.assertRaises(MultistepInitializationError):
			with s.open_store() as events:
				s.set_scheme(multi_scheme, events)

class Test_Access(unittest.TestCase):
	"""
	Test the Solver.get_events method.
	"""
	def setUp(self):
		self.s = Solver(ExplicitEuler(.1), System(partial(const_f, 1.)))
		self.time = 30
		self.s.initialize(u0=np.array([0.]),time=self.time)

	def test_access(self):
		self.s.run()
		sampling_rate = .5
		time = 15
		evts = self.s.get_events(t0=0, time=time, sampling_rate=sampling_rate)
		npt.assert_almost_equal(len(evts.T), len(self.s)*sampling_rate/2, -1) # approx 1/4 of total nb of events
		## self.assertEqual(len(evts.T), 250)
		npt.assert_array_almost_equal(evts[:,-1], np.array([time, time]))

	def test_notrun(self):
		with self.assertRaises(Solver.NotRun):
			self.s.get_events()

class TestSolver(unittest.TestCase):
	def setUp(self):
		self.setup_solver()

	def setup_solver(self):
		self.solver = Solver(ExplicitEuler(h=.1), System(f))
		self.solver.store = Store(None)

	dim = 1
	def set_system(self, f):
		self.solver.system = System(f)

	def test_scheme_str(self):
		# should not raise an exception even though h is not yet set in the underlying scheme:
		print(str(self.solver))

	def test_initialize(self):
		u0 = np.random.rand(self.dim)
		self.solver.initialize(u0=u0,)
		self.assertEqual(self.solver.time, Solver.time)
		self.assertEqual(len(self.solver), 1)

	def test_initialize_twice(self):
		if isinstance(self.solver.store, SimpleStore):
			pytest.skip()
		u0 = np.random.rand(self.dim)
		self.solver.initialize(u0=u0)
		with self.assertRaises(PyTableStore.AlreadyInitialized):
			self.solver.initialize(u0=u0)

	@pytest.mark.skip('Not relevant anymore, time step is initialized directly at the scheme level')
	def test_initialize_scheme(self):
		h = 10.
		self.solver.initialize(u0=np.random.rand(self.dim),)
		e0 = self.solver.initial()
		with self.solver.open_store() as events:
			self.solver.set_scheme(self.solver.scheme, events)
		self.solver.step(e0[-1], e0[:-1],)
		self.assertEqual(self.solver.scheme.h, h)

from functools import partial
const_r = partial(const_f, 1.)
const_c = partial(const_f, 1.j)

schemes = [
		ExplicitEuler(h=.1),
		ImplicitEuler(h=.1),
		ExplicitTrapezoidal(h=.1),
		RungeKutta4(h=.1),
		ImplicitMidPoint(h=.1),
		RungeKutta34(h=.1),
		ode15s(h=.1),

]

@pytest.fixture(params=schemes, ids=repr)
def scheme(request):
	return request.param

class TestLinQuad():
	def test_quadratic(self, scheme):
		sys = System(time_f)
		solver = Solver(system=sys, scheme=scheme)
		solver.initialize(u0=1., time=1.,)
		solver.run()
		# u'(t) = t; u(0) = u0; => u(t) == u0 + t**2/2
		npt.assert_array_almost_equal(solver.final(), np.array([3/2,1.]), decimal=1)

	def check_const(self, f, u0, expected, scheme):
		"""should solve the f=c exactly"""
		sys = System(f)
		solver = Solver(system=sys, scheme=scheme)
		solver.initialize(u0=u0, time=1.,)
		solver.run()
		expected_event = np.hstack([expected, 1.])
		npt.assert_almost_equal(solver.final(), expected_event, 1)

	def test_real_const(self, scheme):
		self.check_const(const_r, 1., 2., scheme)

	@pytest.mark.skip('Current nonlinear solver does not work with the complex type.')
	def test_complex_const(self, scheme):
		self.check_const(const_c, 1.+0j, 1.+1.j, scheme)

	def test_repr(self, scheme):
		expected = '<Solver: {0}'.format(repr(scheme))
		solver = Solver(scheme=scheme, system=System(f))
		r = repr(solver)
		assert r.startswith(expected)
		# if solver.init_scheme is not None:
		# 	self.assertRegex(r, repr(self.solver.init_scheme))

# class Test_AB(Harness_Solver, unittest.TestCase):
# 	def setup_solver(self):
# 		multi_scheme = AdamsBashforth2(.1)
# 		self.solver = Solver(multi_scheme, System(f), init_scheme=ExplicitEuler(h=.1))

# class Test_LawsonEuler(Harness_Solver_NoComplex, unittest.TestCase):
# 	def set_system(self, f):
# 		self.solver.system = NoLinear(f,self.dim)
# 	def setup_solver(self):
# 		self.solver = Solver(LawsonEuler(h=.1), NoLinear(f,self.dim))

class Test_RK34Vdp(unittest.TestCase):
	def setUp(self):
		time = 7.8
		self.h_init = time/50
		self.scheme = RungeKutta34(h=self.h_init)
		self.s = Solver(self.scheme, VanderPol(mu=1.))
		self.s.initialize(u0 = array([.2,1]), time=time, )

	def test_run(self):
		self.s.run()
		self.assertLess(self.scheme.h, self.h_init)

class TestStability(unittest.TestCase):
	def test_unstable(self):
		with self.assertRaises(Solver.Unstable):
			s = Solver(LawsonEuler(h=10.), Linear(np.array([[1.e2]])))
			s.initialize(u0 = 1., time = 100,)
			s.run()

class DummyException(Exception):
	pass

class LimitedSys(System):
	def __init__(self, limit):
		self.limit = limit
		self.i = 0
	def f(self, t, x):
		if self.i < self.limit:
			self.i += 1
			return 0
		else:
			raise DummyException()

class Test_FinalTimeExceptions(unittest.TestCase):
	limit = 20
	def setUp(self):
		self.sys = LimitedSys(self.limit)
		self.scheme = ExplicitEuler(h=.1)
		self.s = Solver(self.scheme, self.sys)
		self.s.catch_runtime = True
		self.s.initialize(u0=0, time=10, )

	def test_final_time_not_reached(self):
		with self.assertRaises(Solver.FinalTimeNotReached):
			self.s.run(max_iter = 1)

	def test_max_iter(self):
		try:
			self.s.run()
		except self.s.RuntimeError:
			pass
		self.assertGreaterEqual(self.s._max_iter, self.s.max_iter_factor*self.s.time/self.scheme.h)
		time = 50
		try:
			self.s.run(50)
		except self.s.RuntimeError:
			pass
		self.assertGreaterEqual(self.s._max_iter, self.s.max_iter_factor*time/self.scheme.h)

	def test_sys_exception(self):
		with self.assertRaises(Solver.RuntimeError):
			self.s.run()

	def test_sys_no_runtime_exception(self):
		self.s.catch_runtime = False
		with self.assertRaises(DummyException):
			self.s.run()

def faulty_function(t,u):
	raise Exception('message')

class Test_Exceptions(unittest.TestCase):
	def setUp(self):
		self.s = Solver(ExplicitEuler(h=.1), Linear(np.array([[1]])))
	def test_no_u0(self):
		with self.assertRaises(Solver.NotInitialized):
			self.s.initialize()
	def test_no_initialize(self):
		with self.assertRaises(Solver.NotInitialized):
			self.s.run()
	def test_unstable(self):
		self.s = Solver(ExplicitEuler(h=.1), Linear(np.array([[float('inf')]])))
		self.s.initialize(u0=np.array([0]))
		with self.assertRaises(Solver.Unstable):
			self.s.run()
	def test_runtime_exception(self):
		self.s = Solver(ExplicitEuler(h=.1), System(faulty_function))
		self.s.catch_runtime = True
		self.s.initialize(u0=0)
		with self.assertRaises(Solver.RuntimeError):
			self.s.run()

class TotSys(System):
	def total(self, xt):
		return np.sum(xt[:-1],axis=0)

def minus_x(t, x):
	return -x

class Test_Simple(unittest.TestCase):
	def setUp(self):
		sys = TotSys(minus_x)
		self.s = Solver(ExplicitEuler(h=.1), sys)

	def test_time(self):
		sol = self.s
		sol.h = Solver.time/10
		sol.initialize(u0=0.)
		sol.run(sol.h)
		npt.assert_(sol.final_time() < Solver.time)

	def test_extra_run(self):
		"""test that an extra run continues from last time"""
		sol = self.s
		sol.initialize(u0=1.)
		sol.run()
		npt.assert_almost_equal(sol.final_time(),Solver.time)
		sol.run()
		npt.assert_almost_equal(sol.final_time(),2*Solver.time)

	def test_plot_args(self):
		self.s.initialize(u0=np.array([1.,1.,1.]))
		self.s.run()
		plt.clf()
		lines = self.s.plot(0,lw=5).axis.lines
		npt.assert_equal(len(lines),1)
		plt.clf()
		lines = self.s.plot(lw=5).axis.lines
		npt.assert_equal(len(lines),3)
		npt.assert_equal(lines[-1].get_linewidth(),5)

	def test_plot_function(self):
		self.s.initialize(u0=np.array([1.,1.,1.]))
		self.s.run()
		lines = self.s.plot_function('total', lw=4).axis.lines
		npt.assert_equal(lines[-1].get_linewidth(), 4)

<|endoftext|>


<commit_before>import galsim
import numpy as np
import pse
import matplotlib.pyplot as plt

### set up basic parameters ###
# how many times to do this (to beat down noise)
n_realization = 100
# file containing theoretical P(k), with fake values added above ell=2000
pkfile = 'test_pse/ps.wmap7lcdm.2000.dat'
theory_tab = galsim.LookupTable(file=pkfile, interpolant='linear')
# prefix for figures
figpref = 'test_pse/galsim_test_pse_'
# number of ell bins used for the estimation
n_ell = 15
# N for our grid used for estimating shears
grid_nx = 100
# length of grid in one dimension (degrees)
theta = 10. # degrees
dtheta = theta/grid_nx
# set verbosity
verbose = False

# Utility for plotting results
def doplot(ell, t, e, b, eb, pref, string, title, rat=None, lim=(1e-7,1e-4),
           bin_theory=None):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(ell, t, label='theory')
    if bin_theory is not None:
        ax.plot(ell, bin_theory, label='binned theory')
    ax.plot(ell, e, label='Observed EE power')
    ax.plot(ell, b, label='Observed BB power')
    ax.plot(ell, eb, label='Observed EB power')
    plt.ylim(lim)
    ax.set_xscale('log')
    ax.set_yscale('log')
    ax.set_xlabel('ell')
    ax.set_ylabel('ell*(ell+1)*C_ell/2pi')
    ax.set_title(title)
    plt.legend(loc=4)
    min_ell = 2.*np.pi/(theta*np.pi/180.)
    max_ell = np.sqrt(2.)*grid_nx*min_ell/2.
    ax.plot(np.array((min_ell,min_ell)), np.array(lim), color='black')
    ax.plot(np.array((max_ell,max_ell)), np.array(lim), color='black')
    figfile = pref + string + '.jpg'
    plt.savefig(figfile)
    print 'Wrote to file ',figfile

    if rat is not None:
        ratio = rat/t
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.plot(ell, ratio, label='vs. theory')
        if bin_theory is not None:
            bin_ratio = rat/bin_theory
            ax.plot(ell, bin_ratio, label='vs. binned theory')
        plt.ylim(0.5,1.5)
        ax.set_xscale('log')
        ax.set_xlabel('ell')
        ax.set_ylabel('Observed / theory')
        ax.set_title(title)
        plt.legend(loc=4)
        ax.plot(np.array((min_ell,min_ell)), np.array((0.5,1.5)), color='black')
        ax.plot(np.array((max_ell,max_ell)), np.array((0.5,1.5)), color='black')
        ax.plot(np.array((0.5*min_ell,1.5*max_ell)),np.array((1.,1.)),color='black')
        figfile = pref + string + '.ratio.jpg'
        plt.savefig(figfile)
        print 'Wrote to file ',figfile

# define the galsim PowerSpectrum objects for the case of only E power, only B, and E+B
test_ps_e=galsim.PowerSpectrum(e_power_function = theory_tab, units='radians')
test_ps_b=galsim.PowerSpectrum(b_power_function = theory_tab, units='radians')
test_ps_eb=galsim.PowerSpectrum(e_power_function = theory_tab,
                                b_power_function = theory_tab, units='radians')

# Set up arrays to store results.
e_p_e = np.zeros((n_ell, n_realization))
e_p_b = np.zeros((n_ell, n_realization))
e_p_eb = np.zeros((n_ell, n_realization))
b_p_e = np.zeros((n_ell, n_realization))
b_p_b = np.zeros((n_ell, n_realization))
b_p_eb = np.zeros((n_ell, n_realization))
eb_p_e = np.zeros((n_ell, n_realization))
eb_p_b = np.zeros((n_ell, n_realization))
eb_p_eb = np.zeros((n_ell, n_realization))

print "Averaging measured power spectra over realizations: ", n_realization
for ireal in range(n_realization):
    if verbose:
        print "Getting shears on a grid with E power only"
    g1, g2 = test_ps_e.buildGriddedShears(grid_spacing=dtheta, ngrid=grid_nx, units=galsim.degrees)
    pse_e = pse.PowerSpectrumEstimator(grid_nx, theta, n_ell)
    if ireal == 0:
        ell, cee_e, cbb_e, ceb_e, c_binned_theory_nowt = pse_e.estimate(g1, g2,
                                                                        theory_func=theory_tab)
        ell, cee_e, cbb_e, ceb_e, c_binned_theory = pse_e.estimate(g1, g2, weight_EE=True,
                                                                   theory_func=theory_tab)
    else:
        ell, cee_e, cbb_e, ceb_e = pse_e.estimate(g1, g2, weight_EE=True)

    if verbose:
        print "Getting shears on a grid with B power only"
    g1, g2 = test_ps_b.buildGriddedShears(grid_spacing=dtheta, ngrid=grid_nx, units=galsim.degrees)
    pse_b = pse.PowerSpectrumEstimator(grid_nx, theta, n_ell)
    ell, cee_b, cbb_b, ceb_b = pse_b.estimate(g1, g2)

    if verbose:
        print "Getting shears on a grid with E and B power"
    g1, g2 = test_ps_eb.buildGriddedShears(grid_spacing=dtheta, ngrid=grid_nx, units=galsim.degrees)
    pse_eb = pse.PowerSpectrumEstimator(grid_nx, theta, n_ell)
    ell, cee_eb, cbb_eb, ceb_eb = pse_eb.estimate(g1, g2, weight_EE=True)

    e_p_e[:,ireal] = cee_e
    e_p_b[:,ireal] = cbb_e
    e_p_eb[:,ireal] = ceb_e
    b_p_e[:,ireal] = cee_b
    b_p_b[:,ireal] = cbb_b
    b_p_eb[:,ireal] = ceb_b
    eb_p_e[:,ireal] = cee_eb
    eb_p_b[:,ireal] = cbb_eb
    eb_p_eb[:,ireal] = ceb_eb

# get average and theoretical powers in a dimensionless way, ell(ell+1) C_ell/(2pi)
e_avgp_e = np.mean(e_p_e,1)*ell*(ell+1)/(2.*np.pi)
e_avgp_b = np.mean(e_p_b,1)*ell*(ell+1)/(2.*np.pi)
e_avgp_eb = np.mean(e_p_eb,1)*ell*(ell+1)/(2.*np.pi)
b_avgp_e = np.mean(b_p_e,1)*ell*(ell+1)/(2.*np.pi)
b_avgp_b = np.mean(b_p_b,1)*ell*(ell+1)/(2.*np.pi)
b_avgp_eb = np.mean(b_p_eb,1)*ell*(ell+1)/(2.*np.pi)
eb_avgp_e = np.mean(eb_p_e,1)*ell*(ell+1)/(2.*np.pi)
eb_avgp_b = np.mean(eb_p_b,1)*ell*(ell+1)/(2.*np.pi)
eb_avgp_eb = np.mean(eb_p_eb,1)*ell*(ell+1)/(2.*np.pi)

theory_p = np.zeros_like(ell)
theory_p_binned = c_binned_theory*ell*(ell+1.)/(2.*np.pi)
theory_p_binned_nowt = c_binned_theory_nowt*ell*(ell+1.)/(2.*np.pi)
for i in range(n_ell):
    theory_p[i] = theory_tab(ell[i])*ell[i]*(ell[i]+1)/(2.*np.pi)

print "Making figures of dimensionless power, and writing to files"
doplot(ell, theory_p, e_avgp_e, e_avgp_b, e_avgp_eb, figpref, 'input_pe',
       'Input P_E only', rat=e_avgp_e, bin_theory=theory_p_binned)
doplot(ell, theory_p, b_avgp_e, b_avgp_b, b_avgp_eb, figpref, 'input_pb',
       'Input P_B only', rat=b_avgp_b, bin_theory=theory_p_binned_nowt)
doplot(ell, theory_p, eb_avgp_e, eb_avgp_b, eb_avgp_eb, figpref, 'input_peb',
       'Input P_EB')
<commit_msg>formatting (#6)<commit_after>import galsim
import numpy as np
import pse
import matplotlib.pyplot as plt

### set up basic parameters ###
# how many times to do this (to beat down noise)
n_realization = 100
# file containing theoretical P(k), with fake values added above ell=2000
pkfile = 'test_pse/ps.wmap7lcdm.2000.dat'
theory_tab = galsim.LookupTable(file=pkfile, interpolant='linear')
# prefix for figures
figpref = 'test_pse/galsim_test_pse_'
# number of ell bins used for the estimation
n_ell = 15
# N for our grid used for estimating shears
grid_nx = 100
# length of grid in one dimension (degrees)
theta = 10. # degrees
dtheta = theta/grid_nx
# set verbosity
verbose = False

# Utility for plotting results
def doplot(ell, t, e, b, eb, pref, string, title, rat=None, lim=(1e-7,1e-4),
           bin_theory=None):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(ell, t, label='theory')
    if bin_theory is not None:
        ax.plot(ell, bin_theory, label='binned theory')
    ax.plot(ell, e, label='Observed EE power')
    ax.plot(ell, b, label='Observed BB power')
    ax.plot(ell, eb, label='Observed EB power')
    plt.ylim(lim)
    ax.set_xscale('log')
    ax.set_yscale('log')
    ax.set_xlabel('ell')
    ax.set_ylabel('ell*(ell+1)*C_ell/2pi')
    ax.set_title(title)
    plt.legend(loc=4)
    min_ell = 2.*np.pi/(theta*np.pi/180.)
    max_ell = np.sqrt(2.)*grid_nx*min_ell/2.
    ax.plot(np.array((min_ell,min_ell)), np.array(lim), color='black')
    ax.plot(np.array((max_ell,max_ell)), np.array(lim), color='black')
    figfile = pref + string + '.jpg'
    plt.savefig(figfile)
    print 'Wrote to file ',figfile

    if rat is not None:
        ratio = rat/t
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.plot(ell, ratio, label='vs. theory')
        if bin_theory is not None:
            bin_ratio = rat/bin_theory
            ax.plot(ell, bin_ratio, label='vs. binned theory')
        plt.ylim(0.5,1.5)
        ax.set_xscale('log')
        ax.set_xlabel('ell')
        ax.set_ylabel('Observed / theory')
        ax.set_title(title)
        plt.legend(loc=4)
        ax.plot(np.array((min_ell,min_ell)), np.array((0.5,1.5)), color='black')
        ax.plot(np.array((max_ell,max_ell)), np.array((0.5,1.5)), color='black')
        ax.plot(np.array((0.5*min_ell,1.5*max_ell)),np.array((1.,1.)),color='black')
        figfile = pref + string + '.ratio.jpg'
        plt.savefig(figfile)
        print 'Wrote to file ', figfile

# define the galsim PowerSpectrum objects for the case of only E power, only B, and E+B
test_ps_e = galsim.PowerSpectrum(e_power_function = theory_tab, units='radians')
test_ps_b = galsim.PowerSpectrum(b_power_function = theory_tab, units='radians')
test_ps_eb = galsim.PowerSpectrum(e_power_function = theory_tab,
                                  b_power_function = theory_tab, units='radians')

# Set up arrays to store results.
e_p_e = np.zeros((n_ell, n_realization))
e_p_b = np.zeros((n_ell, n_realization))
e_p_eb = np.zeros((n_ell, n_realization))
b_p_e = np.zeros((n_ell, n_realization))
b_p_b = np.zeros((n_ell, n_realization))
b_p_eb = np.zeros((n_ell, n_realization))
eb_p_e = np.zeros((n_ell, n_realization))
eb_p_b = np.zeros((n_ell, n_realization))
eb_p_eb = np.zeros((n_ell, n_realization))

print "Averaging measured power spectra over realizations: ", n_realization
for ireal in range(n_realization):
    if verbose:
        print "Getting shears on a grid with E power only"
    g1, g2 = test_ps_e.buildGriddedShears(grid_spacing=dtheta, ngrid=grid_nx, units=galsim.degrees)
    pse_e = pse.PowerSpectrumEstimator(grid_nx, theta, n_ell)
    if ireal == 0:
        ell, cee_e, cbb_e, ceb_e, c_binned_theory_nowt = pse_e.estimate(g1, g2,
                                                                        theory_func=theory_tab)
        ell, cee_e, cbb_e, ceb_e, c_binned_theory = pse_e.estimate(g1, g2, weight_EE=True,
                                                                   theory_func=theory_tab)
    else:
        ell, cee_e, cbb_e, ceb_e = pse_e.estimate(g1, g2, weight_EE=True)

    if verbose:
        print "Getting shears on a grid with B power only"
    g1, g2 = test_ps_b.buildGriddedShears(grid_spacing=dtheta, ngrid=grid_nx, units=galsim.degrees)
    pse_b = pse.PowerSpectrumEstimator(grid_nx, theta, n_ell)
    ell, cee_b, cbb_b, ceb_b = pse_b.estimate(g1, g2)

    if verbose:
        print "Getting shears on a grid with E and B power"
    g1, g2 = test_ps_eb.buildGriddedShears(grid_spacing=dtheta, ngrid=grid_nx, units=galsim.degrees)
    pse_eb = pse.PowerSpectrumEstimator(grid_nx, theta, n_ell)
    ell, cee_eb, cbb_eb, ceb_eb = pse_eb.estimate(g1, g2, weight_EE=True)

    e_p_e[:,ireal] = cee_e
    e_p_b[:,ireal] = cbb_e
    e_p_eb[:,ireal] = ceb_e
    b_p_e[:,ireal] = cee_b
    b_p_b[:,ireal] = cbb_b
    b_p_eb[:,ireal] = ceb_b
    eb_p_e[:,ireal] = cee_eb
    eb_p_b[:,ireal] = cbb_eb
    eb_p_eb[:,ireal] = ceb_eb

# get average and theoretical powers in a dimensionless way, ell(ell+1) C_ell/(2pi)
e_avgp_e = np.mean(e_p_e,1)*ell*(ell+1)/(2.*np.pi)
e_avgp_b = np.mean(e_p_b,1)*ell*(ell+1)/(2.*np.pi)
e_avgp_eb = np.mean(e_p_eb,1)*ell*(ell+1)/(2.*np.pi)
b_avgp_e = np.mean(b_p_e,1)*ell*(ell+1)/(2.*np.pi)
b_avgp_b = np.mean(b_p_b,1)*ell*(ell+1)/(2.*np.pi)
b_avgp_eb = np.mean(b_p_eb,1)*ell*(ell+1)/(2.*np.pi)
eb_avgp_e = np.mean(eb_p_e,1)*ell*(ell+1)/(2.*np.pi)
eb_avgp_b = np.mean(eb_p_b,1)*ell*(ell+1)/(2.*np.pi)
eb_avgp_eb = np.mean(eb_p_eb,1)*ell*(ell+1)/(2.*np.pi)

theory_p = np.zeros_like(ell)
theory_p_binned = c_binned_theory*ell*(ell+1.)/(2.*np.pi)
theory_p_binned_nowt = c_binned_theory_nowt*ell*(ell+1.)/(2.*np.pi)
for i in range(n_ell):
    theory_p[i] = theory_tab(ell[i])*ell[i]*(ell[i]+1)/(2.*np.pi)

print "Making figures of dimensionless power, and writing to files"
doplot(ell, theory_p, e_avgp_e, e_avgp_b, e_avgp_eb, figpref, 'input_pe',
       'Input P_E only', rat=e_avgp_e, bin_theory=theory_p_binned)
doplot(ell, theory_p, b_avgp_e, b_avgp_b, b_avgp_eb, figpref, 'input_pb',
       'Input P_B only', rat=b_avgp_b, bin_theory=theory_p_binned_nowt)
doplot(ell, theory_p, eb_avgp_e, eb_avgp_b, eb_avgp_eb, figpref, 'input_peb',
       'Input P_EB')
<|endoftext|>