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

__author__ = 'Adam R. Smith'

import uuid

from pyon.core.bootstrap import IonObject
from pyon.core.exception import NotFound
from pyon.ion.resource import RT
from pyon.ion.service import BaseService
from pyon.util.int_test import IonIntegrationTestCase

class TestService(BaseService):
    name = 'test-service'
    clients = IonObject(RT.Resource)

class ServiceTest(IonIntegrationTestCase):

    def setUp(self):
        self._start_container()
        self.rr = self.container.resource_registry

    def test_serve(self):
        # TODO: Make an equivalent of R1's ServiceProcess
        srv = TestService()
        #srv.serve_forever()

    def test_validate_resource_id(self):
        srv = TestService()
        srv.clients.resource_registry = self.rr
        res_obj1 = IonObject(RT.ActorIdentity)

        newid = uuid.uuid4().hex
        rid1, _ = self.rr.create(res_obj1, object_id=newid)
        res_val_obj = srv._validate_resource_id("_id", rid1, optional=True)
        self.assertTrue(res_val_obj)
        self.assertRaises(NotFound, srv._validate_resource_id, arg_name="_id",
                          resource_id="badId",
                          optional=False)
        self.assertIsNone(srv._validate_resource_id("_id", "", optional=True))
        self.assertIsNone(srv._validate_resource_id("_id", None, optional=True))
        newid2 = uuid.uuid4().hex
        with self.assertRaises(NotFound):
            srv._validate_resource_id("_id", newid2, optional=True)
        self.rr.delete(rid1)
<commit_msg>Fix test_validate_resource_id<commit_after>#!/usr/bin/env python

__author__ = 'Adam R. Smith'

import uuid

from pyon.util.int_test import IonIntegrationTestCase

from pyon.core.bootstrap import IonObject
from pyon.core.exception import NotFound
from pyon.ion.resource import RT
from pyon.ion.service import BaseService
from pyon.util.containers import DotDict

class TestService(BaseService):
    name = 'test-service'
    clients = DotDict()

class ServiceTest(IonIntegrationTestCase):

    def setUp(self):
        self._start_container()
        self.rr = self.container.resource_registry

    def test_serve(self):
        srv = TestService()
        #srv.serve_forever()

    def test_validate_resource_id(self):
        srv = TestService()
        srv.clients.resource_registry = self.rr
        res_obj1 = IonObject(RT.ActorIdentity)

        newid = uuid.uuid4().hex
        rid1, _ = self.rr.create(res_obj1, object_id=newid)
        res_val_obj = srv._validate_resource_id("_id", rid1, optional=True)
        self.assertTrue(res_val_obj)
        self.assertRaises(NotFound, srv._validate_resource_id, arg_name="_id",
                          resource_id="badId",
                          optional=False)
        self.assertIsNone(srv._validate_resource_id("_id", "", optional=True))
        self.assertIsNone(srv._validate_resource_id("_id", None, optional=True))
        newid2 = uuid.uuid4().hex
        with self.assertRaises(NotFound):
            srv._validate_resource_id("_id", newid2, optional=True)
        self.rr.delete(rid1)
<|endoftext|>


<commit_before># Licensed under GPL3 (see LICENSE)
# coding=utf-8

"""
config.py - Configuration data and utility functions
"""

import os
import pkg_resources

import astropy.units as u

def recursive_subclasses(cls):
    """
    The __subclasses__() method only goes one level deep, but various classes can be separated by multiple
    inheritance layers. This function recursively walks through the inheritance tree and returns a list of all
    subclasses at all levels that inherit from the given class.

    Parameters
    ----------
    cls: any python Class
        Python class to get list of subclasses for

    Returns
    -------
    all_subclasses: list
        List of all subclasses that ultimately inherit from cls
    """
    all_subclasses = []

    top_subclasses = cls.__subclasses__()
    all_subclasses.extend(top_subclasses)

    for s in top_subclasses:
        all_subclasses.extend(recursive_subclasses(s))

    return all_subclasses

def merge_config(*dicts):
    """
    This takes a list of python dicts and merges them into a single dict.  It is set up to
    assure that later arguments will take precedence over earlier ones by default.

    Parameters
    ----------
    dicts: list
        List of dicts to merge into a single dict

    Returns
    -------
    updated: dict
        Arguments combined into a single dict.  Later arguments take precedence over earlier arguments
        and dicts take precedence over non-dict values.
    """
    updated = {}

    # grab all of the keys
    keys = set()
    for o in dicts:
        keys = keys.union(set(o))

    for key in keys:
        values = [o[key] for o in dicts if key in o]
        # find values that are dicts so we can recurse through them
        maps = [value for value in values if isinstance(value, dict)]
        if maps:
            updated[key] = merge_config(*maps)
        else:
            # if not a dict, then return the last value we have since later arguments
            # take precendence
            updated[key] = values[-1]
    return updated

"""
Optics numbers are taken from http://www.mmto.org/sites/default/files/mmt_conv7_2.pdf
"""
mmt_config = {
    "telescope": {
        "diameter": 6502.4 * u.mm,  # primary diameter
        "bcv_radius": 3228.5 * u.mm,  # radius to use when normalizing BCV finite element coordinates
        "n_supports": 4,  # number of secondary support struts
        "support_width": 0.12 * u.m,  # width of support struts in meters
        "support_offset": 45. * u.deg,  # offset of support struts in degrees
        # influence matrix to map actuator forces to surface displacement
        "surf2act_file": pkg_resources.resource_filename(__name__, os.path.join("data", "Surf2ActTEL_32.bin")),
        # coordinates of finite element nodes used in surf2act
        "nodecoor_file": pkg_resources.resource_filename(__name__, os.path.join("data", "bcv_node_coordinates.dat")),
        # coordinates of the force actuators
        "actuator_file": pkg_resources.resource_filename(__name__, os.path.join("data", "actuator_coordinates.dat"))
    },
    "secondary": {
        "f5": {
            "diameter": 1688.0 * u.mm,  # clear aperture of secondary
            "theta_cc": 79.0 * u.nm / u.arcsec,  # nm of coma per arcsec of center-of-curvature tilt.
            "cc_trans": 25.0 * u.um / u.arcsec,  # um of hexapod translation per arcsec of center-of-curvature tilt.
            "zc_trans": 9.45 * u.um / u.arcsec,  # um of hexapod translation per arcsec of zero-coma tilt.
            "focus_trans": 40.8 * u.nm / u.um  # nm of defocus per um of hexapod Z (focus) translation.
        },
        "f9": {
            "diameter": 1006.7 * u.mm,
            "theta_cc": 44.4 * u.nm / u.arcsec,
            "cc_trans": 13.6 * u.um / u.arcsec,
            "zc_trans": 5.86 * u.um / u.arcsec,
            "focus_trans": 34.7 * u.nm / u.um
        }
    },
    "wfs": {
        "f5": {
            "secondary": "f5",  # secondary used with WFS system
            "rotation": 234.0 * u.deg,  # rotation of aperture locations w.r.t. the primary mirror
            "pix_size": 0.135 * u.arcsec,  # arcsec per WFS detector pixel
            "pup_size": 460,  # pixels
            "pup_inner": 65,  # inner obscuration radius in pixels
            "pup_offset": [-0.42, 0.47],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f5_hecto_ref.fits")),
            "modes": {
                "megacam": {
                    "ref_zern": {
                        "Z04": -468. * u.nm,  # defocus
                        "Z11": -80. * u.nm  # primary spherical
                    },
                },
                "hecto": {
                    "ref_zern": {
                        "Z04": -2810. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "maestro": {
                    "ref_zern": {
                        "Z04": -2820. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "swirc": {
                    "ref_zern": {
                        "Z04": -2017. * u.nm,
                        "Z11": -1079. * u.nm
                    }
                }
            }
        },
        "f9": {
            "secondary": "f9",
            "rotation": -225. * u.deg,
            "pix_size": 0.119 * u.arcsec,  # old KX260e detector with 20 um pixels
            "pup_size": 460,  # pupil outer diameter in pixels
            "pup_inner": 50,  # inner obscuration radius in pixels
            "pup_offset": [0.3, 0.45],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f9_ref.fits")),
            "modes": {
                "blue": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "red": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "spol": {
                    "ref_zern": {
                        "Z04": -308. * u.nm
                    },
                }
            }
        },
        "mmirs": {
            "secondary": "f5",
            "rotation": 180. * u.deg,  # this is referenced to camera2. camera1 is camera2+180, but is flipped by image acq
            "pix_size": 0.156 * u.arcsec,
            "pup_size": 360,  # pixels
            "pup_inner": 50,
            "pup_offset": [0.0, -0.55],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "modes": {
                "mmirs1": {
                    "ref_zern": {
                        "Z04": -2918. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera1_ref.fits")
                    ),
                },
                "mmirs2": {
                    "ref_zern": {
                        "Z04": 1912. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera2_ref.fits")
                    ),
                }
            }
        }
    }
}
<commit_msg>tweak f/9 pupil config<commit_after># Licensed under GPL3 (see LICENSE)
# coding=utf-8

"""
config.py - Configuration data and utility functions
"""

import os
import pkg_resources

import astropy.units as u

def recursive_subclasses(cls):
    """
    The __subclasses__() method only goes one level deep, but various classes can be separated by multiple
    inheritance layers. This function recursively walks through the inheritance tree and returns a list of all
    subclasses at all levels that inherit from the given class.

    Parameters
    ----------
    cls: any python Class
        Python class to get list of subclasses for

    Returns
    -------
    all_subclasses: list
        List of all subclasses that ultimately inherit from cls
    """
    all_subclasses = []

    top_subclasses = cls.__subclasses__()
    all_subclasses.extend(top_subclasses)

    for s in top_subclasses:
        all_subclasses.extend(recursive_subclasses(s))

    return all_subclasses

def merge_config(*dicts):
    """
    This takes a list of python dicts and merges them into a single dict.  It is set up to
    assure that later arguments will take precedence over earlier ones by default.

    Parameters
    ----------
    dicts: list
        List of dicts to merge into a single dict

    Returns
    -------
    updated: dict
        Arguments combined into a single dict.  Later arguments take precedence over earlier arguments
        and dicts take precedence over non-dict values.
    """
    updated = {}

    # grab all of the keys
    keys = set()
    for o in dicts:
        keys = keys.union(set(o))

    for key in keys:
        values = [o[key] for o in dicts if key in o]
        # find values that are dicts so we can recurse through them
        maps = [value for value in values if isinstance(value, dict)]
        if maps:
            updated[key] = merge_config(*maps)
        else:
            # if not a dict, then return the last value we have since later arguments
            # take precendence
            updated[key] = values[-1]
    return updated

"""
Optics numbers are taken from http://www.mmto.org/sites/default/files/mmt_conv7_2.pdf
"""
mmt_config = {
    "telescope": {
        "diameter": 6502.4 * u.mm,  # primary diameter
        "bcv_radius": 3228.5 * u.mm,  # radius to use when normalizing BCV finite element coordinates
        "n_supports": 4,  # number of secondary support struts
        "support_width": 0.12 * u.m,  # width of support struts in meters
        "support_offset": 45. * u.deg,  # offset of support struts in degrees
        # influence matrix to map actuator forces to surface displacement
        "surf2act_file": pkg_resources.resource_filename(__name__, os.path.join("data", "Surf2ActTEL_32.bin")),
        # coordinates of finite element nodes used in surf2act
        "nodecoor_file": pkg_resources.resource_filename(__name__, os.path.join("data", "bcv_node_coordinates.dat")),
        # coordinates of the force actuators
        "actuator_file": pkg_resources.resource_filename(__name__, os.path.join("data", "actuator_coordinates.dat"))
    },
    "secondary": {
        "f5": {
            "diameter": 1688.0 * u.mm,  # clear aperture of secondary
            "theta_cc": 79.0 * u.nm / u.arcsec,  # nm of coma per arcsec of center-of-curvature tilt.
            "cc_trans": 25.0 * u.um / u.arcsec,  # um of hexapod translation per arcsec of center-of-curvature tilt.
            "zc_trans": 9.45 * u.um / u.arcsec,  # um of hexapod translation per arcsec of zero-coma tilt.
            "focus_trans": 40.8 * u.nm / u.um  # nm of defocus per um of hexapod Z (focus) translation.
        },
        "f9": {
            "diameter": 1006.7 * u.mm,
            "theta_cc": 44.4 * u.nm / u.arcsec,
            "cc_trans": 13.6 * u.um / u.arcsec,
            "zc_trans": 5.86 * u.um / u.arcsec,
            "focus_trans": 34.7 * u.nm / u.um
        }
    },
    "wfs": {
        "f5": {
            "secondary": "f5",  # secondary used with WFS system
            "rotation": 234.0 * u.deg,  # rotation of aperture locations w.r.t. the primary mirror
            "pix_size": 0.135 * u.arcsec,  # arcsec per WFS detector pixel
            "pup_size": 460,  # pixels
            "pup_inner": 65,  # inner obscuration radius in pixels
            "pup_offset": [-0.42, 0.47],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f5_hecto_ref.fits")),
            "modes": {
                "megacam": {
                    "ref_zern": {
                        "Z04": -468. * u.nm,  # defocus
                        "Z11": -80. * u.nm  # primary spherical
                    },
                },
                "hecto": {
                    "ref_zern": {
                        "Z04": -2810. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "maestro": {
                    "ref_zern": {
                        "Z04": -2820. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "swirc": {
                    "ref_zern": {
                        "Z04": -2017. * u.nm,
                        "Z11": -1079. * u.nm
                    }
                }
            }
        },
        "f9": {
            "secondary": "f9",
            "rotation": -225. * u.deg,
            "pix_size": 0.119 * u.arcsec,  # old KX260e detector with 20 um pixels
            "pup_size": 460,  # pupil outer diameter in pixels
            "pup_inner": 55,  # inner obscuration radius in pixels
            "pup_offset": [0.35, 0.7],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f9_ref.fits")),
            "modes": {
                "blue": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "red": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "spol": {
                    "ref_zern": {
                        "Z04": -308. * u.nm
                    },
                }
            }
        },
        "mmirs": {
            "secondary": "f5",
            "rotation": 180. * u.deg,  # this is referenced to camera2. camera1 is camera2+180, but is flipped by image acq
            "pix_size": 0.156 * u.arcsec,
            "pup_size": 360,  # pixels
            "pup_inner": 50,
            "pup_offset": [0.0, -0.55],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "modes": {
                "mmirs1": {
                    "ref_zern": {
                        "Z04": -2918. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera1_ref.fits")
                    ),
                },
                "mmirs2": {
                    "ref_zern": {
                        "Z04": 1912. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera2_ref.fits")
                    ),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before># Licensed under GPL3 (see LICENSE)
# coding=utf-8

"""
config.py - Configuration data and utility functions
"""

import os
import pkg_resources

import astropy.units as u

def recursive_subclasses(cls):
    """
    The __subclasses__() method only goes one level deep, but various classes can be separated by multiple
    inheritance layers. This function recursively walks through the inheritance tree and returns a list of all
    subclasses at all levels that inherit from the given class.

    Parameters
    ----------
    cls: any python Class
        Python class to get list of subclasses for

    Returns
    -------
    all_subclasses: list
        List of all subclasses that ultimately inherit from cls
    """
    all_subclasses = []

    top_subclasses = cls.__subclasses__()
    all_subclasses.extend(top_subclasses)

    for s in top_subclasses:
        all_subclasses.extend(recursive_subclasses(s))

    return all_subclasses

def merge_config(*dicts):
    """
    This takes a list of python dicts and merges them into a single dict.  It is set up to
    assure that later arguments will take precedence over earlier ones by default.

    Parameters
    ----------
    dicts: list
        List of dicts to merge into a single dict

    Returns
    -------
    updated: dict
        Arguments combined into a single dict.  Later arguments take precedence over earlier arguments
        and dicts take precedence over non-dict values.
    """
    updated = {}

    # grab all of the keys
    keys = set()
    for o in dicts:
        keys = keys.union(set(o))

    for key in keys:
        values = [o[key] for o in dicts if key in o]
        # find values that are dicts so we can recurse through them
        maps = [value for value in values if isinstance(value, dict)]
        if maps:
            updated[key] = merge_config(*maps)
        else:
            # if not a dict, then return the last value we have since later arguments
            # take precendence
            updated[key] = values[-1]
    return updated

"""
Optics numbers are taken from http://www.mmto.org/sites/default/files/mmt_conv7_2.pdf
"""
mmt_config = {
    "telescope": {
        "diameter": 6502.4 * u.mm,  # primary diameter
        "bcv_radius": 3228.5 * u.mm,  # radius to use when normalizing BCV finite element coordinates
        "n_supports": 4,  # number of secondary support struts
        "support_width": 0.12 * u.m,  # width of support struts in meters
        "support_offset": 45. * u.deg,  # offset of support struts in degrees
        # influence matrix to map actuator forces to surface displacement
        "surf2act_file": pkg_resources.resource_filename(__name__, os.path.join("data", "Surf2ActTEL_32.bin")),
        # coordinates of finite element nodes used in surf2act
        "nodecoor_file": pkg_resources.resource_filename(__name__, os.path.join("data", "bcv_node_coordinates.dat")),
        # coordinates of the force actuators
        "actuator_file": pkg_resources.resource_filename(__name__, os.path.join("data", "actuator_coordinates.dat"))
    },
    "secondary": {
        "f5": {
            "diameter": 1688.0 * u.mm,  # clear aperture of secondary
            "theta_cc": 79.0 * u.nm / u.arcsec,  # nm of coma per arcsec of center-of-curvature tilt.
            "cc_trans": 25.0 * u.um / u.arcsec,  # um of hexapod translation per arcsec of center-of-curvature tilt.
            "zc_trans": 9.45 * u.um / u.arcsec,  # um of hexapod translation per arcsec of zero-coma tilt.
            "focus_trans": 40.8 * u.nm / u.um  # nm of defocus per um of hexapod Z (focus) translation.
        },
        "f9": {
            "diameter": 1006.7 * u.mm,
            "theta_cc": 44.4 * u.nm / u.arcsec,
            "cc_trans": 13.6 * u.um / u.arcsec,
            "zc_trans": 5.86 * u.um / u.arcsec,
            "focus_trans": 34.7 * u.nm / u.um
        }
    },
    "wfs": {
        "f5": {
            "secondary": "f5",  # secondary used with WFS system
            "rotation": 234.0 * u.deg,  # rotation of aperture locations w.r.t. the primary mirror
            "pix_size": 0.135 * u.arcsec,  # arcsec per WFS detector pixel
            "pup_size": 460,  # pixels
            "pup_inner": 65,  # inner obscuration radius in pixels
            "pup_offset": [-0.42, 0.47],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "back_h": 0.99,
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f5_hecto_ref.fits")),
            "modes": {
                "megacam": {
                    "ref_zern": {
                        "Z04": -468. * u.nm,  # defocus
                        "Z11": -80. * u.nm  # primary spherical
                    },
                },
                "hecto": {
                    "ref_zern": {
                        "Z04": -2810. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "maestro": {
                    "ref_zern": {
                        "Z04": -2820. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "swirc": {
                    "ref_zern": {
                        "Z04": -2017. * u.nm,
                        "Z11": -1079. * u.nm
                    }
                }
            }
        },
        "f9": {
            "secondary": "f9",
            "rotation": -225. * u.deg,
            "pix_size": 0.119 * u.arcsec,  # old KX260e detector with 20 um pixels
            "pup_size": 440,  # pupil outer diameter in pixels
            "pup_inner": 55,  # inner obscuration radius in pixels
            "pup_offset": [0.4, 0.75],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "back_h": 0.9,
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f9_ref.fits")),
            "modes": {
                "blue": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "red": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "spol": {
                    "ref_zern": {
                        "Z04": -308. * u.nm
                    },
                }
            }
        },
        "mmirs": {
            "secondary": "f5",
            "rotation": 180. * u.deg,  # this is referenced to camera2. camera1 is camera2+180, but is flipped by image acq
            "pix_size": 0.156 * u.arcsec,
            "pup_size": 340,  # pixels
            "pup_inner": 50,
            "pup_offset": [0.0, -0.55],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "back_h": 0.9,
            "aberr_table_file": pkg_resources.resource_filename(__name__, os.path.join("data", "mmirs.offaxis.coeffs.dat")),
            "modes": {
                "mmirs1": {
                    "ref_zern": {
                        "Z04": -2918. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera1_ref.fits")
                    ),
                },
                "mmirs2": {
                    "ref_zern": {
                        "Z04": 1912. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera2_ref.fits")
                    ),
                }
            }
        }
    }
}
<commit_msg>config.py - add mapping from old shwfs mode ordering to Noll order<commit_after># Licensed under GPL3 (see LICENSE)
# coding=utf-8

"""
config.py - Configuration data and utility functions
"""

import os
import pkg_resources

import astropy.units as u

def recursive_subclasses(cls):
    """
    The __subclasses__() method only goes one level deep, but various classes can be separated by multiple
    inheritance layers. This function recursively walks through the inheritance tree and returns a list of all
    subclasses at all levels that inherit from the given class.

    Parameters
    ----------
    cls: any python Class
        Python class to get list of subclasses for

    Returns
    -------
    all_subclasses: list
        List of all subclasses that ultimately inherit from cls
    """
    all_subclasses = []

    top_subclasses = cls.__subclasses__()
    all_subclasses.extend(top_subclasses)

    for s in top_subclasses:
        all_subclasses.extend(recursive_subclasses(s))

    return all_subclasses

def merge_config(*dicts):
    """
    This takes a list of python dicts and merges them into a single dict.  It is set up to
    assure that later arguments will take precedence over earlier ones by default.

    Parameters
    ----------
    dicts: list
        List of dicts to merge into a single dict

    Returns
    -------
    updated: dict
        Arguments combined into a single dict.  Later arguments take precedence over earlier arguments
        and dicts take precedence over non-dict values.
    """
    updated = {}

    # grab all of the keys
    keys = set()
    for o in dicts:
        keys = keys.union(set(o))

    for key in keys:
        values = [o[key] for o in dicts if key in o]
        # find values that are dicts so we can recurse through them
        maps = [value for value in values if isinstance(value, dict)]
        if maps:
            updated[key] = merge_config(*maps)
        else:
            # if not a dict, then return the last value we have since later arguments
            # take precendence
            updated[key] = values[-1]
    return updated

"""
Optics numbers are taken from http://www.mmto.org/sites/default/files/mmt_conv7_2.pdf
"""
mmt_config = {
    "telescope": {
        "diameter": 6502.4 * u.mm,  # primary diameter
        "bcv_radius": 3228.5 * u.mm,  # radius to use when normalizing BCV finite element coordinates
        "n_supports": 4,  # number of secondary support struts
        "support_width": 0.12 * u.m,  # width of support struts in meters
        "support_offset": 45. * u.deg,  # offset of support struts in degrees
        # influence matrix to map actuator forces to surface displacement
        "surf2act_file": pkg_resources.resource_filename(__name__, os.path.join("data", "Surf2ActTEL_32.bin")),
        # coordinates of finite element nodes used in surf2act
        "nodecoor_file": pkg_resources.resource_filename(__name__, os.path.join("data", "bcv_node_coordinates.dat")),
        # coordinates of the force actuators
        "actuator_file": pkg_resources.resource_filename(__name__, os.path.join("data", "actuator_coordinates.dat")),
        "zern_map": {  # map the old zernike mode indexing scheme to the Noll scheme used in ZernikeVector
            "Z02": 0,
            "Z03": 1,
            "Z04": 2,
            "Z05": 3,
            "Z06": 4,
            "Z07": 5,
            "Z08": 6,
            "Z09": 8,
            "Z10": 9,
            "Z11": 7,
            "Z12": 11,
            "Z13": 10,
            "Z14": 13,
            "Z15": 12,
            "Z16": 16,
            "Z17": 17,
            "Z18": 14,
            "Z19": 15,
            "Z22": 18
        }
    },
    "secondary": {
        "f5": {
            "diameter": 1688.0 * u.mm,  # clear aperture of secondary
            "theta_cc": 79.0 * u.nm / u.arcsec,  # nm of coma per arcsec of center-of-curvature tilt.
            "cc_trans": 25.0 * u.um / u.arcsec,  # um of hexapod translation per arcsec of center-of-curvature tilt.
            "zc_trans": 9.45 * u.um / u.arcsec,  # um of hexapod translation per arcsec of zero-coma tilt.
            "focus_trans": 40.8 * u.nm / u.um  # nm of defocus per um of hexapod Z (focus) translation.
        },
        "f9": {
            "diameter": 1006.7 * u.mm,
            "theta_cc": 44.4 * u.nm / u.arcsec,
            "cc_trans": 13.6 * u.um / u.arcsec,
            "zc_trans": 5.86 * u.um / u.arcsec,
            "focus_trans": 34.7 * u.nm / u.um
        }
    },
    "wfs": {
        "f5": {
            "secondary": "f5",  # secondary used with WFS system
            "rotation": 234.0 * u.deg,  # rotation of aperture locations w.r.t. the primary mirror
            "pix_size": 0.135 * u.arcsec,  # arcsec per WFS detector pixel
            "pup_size": 460,  # pixels
            "pup_inner": 65,  # inner obscuration radius in pixels
            "pup_offset": [-0.42, 0.47],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "back_h": 0.99,
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f5_hecto_ref.fits")),
            "modes": {
                "megacam": {
                    "ref_zern": {
                        "Z04": -468. * u.nm,  # defocus
                        "Z11": -80. * u.nm  # primary spherical
                    },
                },
                "hecto": {
                    "ref_zern": {
                        "Z04": -2810. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "maestro": {
                    "ref_zern": {
                        "Z04": -2820. * u.nm,
                        "Z11": -150. * u.nm
                    },
                },
                "swirc": {
                    "ref_zern": {
                        "Z04": -2017. * u.nm,
                        "Z11": -1079. * u.nm
                    }
                }
            }
        },
        "f9": {
            "secondary": "f9",
            "rotation": -225. * u.deg,
            "pix_size": 0.119 * u.arcsec,  # old KX260e detector with 20 um pixels
            "pup_size": 440,  # pupil outer diameter in pixels
            "pup_inner": 55,  # inner obscuration radius in pixels
            "pup_offset": [0.4, 0.75],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "back_h": 0.9,
            "reference_file": pkg_resources.resource_filename(__name__, os.path.join("data", "ref_images", "f9_ref.fits")),
            "modes": {
                "blue": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "red": {
                    "ref_zern": {
                        "Z04": 7982. * u.nm
                    },
                },
                "spol": {
                    "ref_zern": {
                        "Z04": -308. * u.nm
                    },
                }
            }
        },
        "mmirs": {
            "secondary": "f5",
            "rotation": 180. * u.deg,  # this is referenced to camera2. camera1 is camera2+180, but is flipped by image acq
            "pix_size": 0.156 * u.arcsec,
            "pup_size": 340,  # pixels
            "pup_inner": 50,
            "pup_offset": [0.0, -0.55],  # [x, y] pupil offset from center of reference aperture pattern
            "m1_gain": 0.5,  # default gain to apply to primary mirror corrections
            "m2_gain": 1.0,  # default gain to apply to secondary mirror corrections
            "nzern": 20,  # number of zernike modes to fit
            "back_h": 0.9,
            "aberr_table_file": pkg_resources.resource_filename(__name__, os.path.join("data", "mmirs.offaxis.coeffs.dat")),
            "modes": {
                "mmirs1": {
                    "ref_zern": {
                        "Z04": -2918. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera1_ref.fits")
                    ),
                },
                "mmirs2": {
                    "ref_zern": {
                        "Z04": 1912. * u.nm
                    },
                    "reference_file": pkg_resources.resource_filename(
                        __name__,
                        os.path.join("data", "ref_images", "mmirs_camera2_ref.fits")
                    ),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe

from frappe.utils import add_days, getdate, cint, cstr

from frappe import throw, _
from erpnext.utilities.transaction_base import TransactionBase, delete_events
from erpnext.stock.utils import get_valid_serial_nos
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee

class MaintenanceSchedule(TransactionBase):
	def generate_schedule(self):
		self.set('schedules', [])
		frappe.db.sql("""delete from `tabMaintenance Schedule Detail`
			where parent=%s""", (self.name))
		count = 1
		for d in self.get('items'):
			self.validate_maintenance_detail()
			s_list = []
			s_list = self.create_schedule_list(d.start_date, d.end_date, d.no_of_visits, d.sales_person)
			for i in range(d.no_of_visits):
				child = self.append('schedules')
				child.item_code = d.item_code
				child.item_name = d.item_name
				child.scheduled_date = s_list[i].strftime('%Y-%m-%d')
				if d.serial_no:
					child.serial_no = d.serial_no
				child.idx = count
				count = count + 1
				child.sales_person = d.sales_person

		self.save()

	def on_submit(self):
		if not self.get('schedules'):
			throw(_("Please click on 'Generate Schedule' to get schedule"))
		self.check_serial_no_added()
		self.validate_schedule()

		email_map = {}
		for d in self.get('items'):
			if d.serial_no:
				serial_nos = get_valid_serial_nos(d.serial_no)
				self.validate_serial_no(serial_nos, d.start_date)
				self.update_amc_date(serial_nos, d.end_date)

			no_email_sp = []
			if d.sales_person not in email_map:
				sp = frappe.get_doc("Sales Person", d.sales_person)
				try:
					email_map[d.sales_person] = sp.get_email_id()
				except frappe.ValidationError:
					no_email_sp.append(d.sales_person)

			if no_email_sp:
				frappe.msgprint(
					frappe._("Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}").format(
						self.owner, "
"+no_email_sp.join("
")
				))

			scheduled_date = frappe.db.sql("""select scheduled_date from
				`tabMaintenance Schedule Detail` where sales_person=%s and item_code=%s and
				parent=%s""", (d.sales_person, d.item_code, self.name), as_dict=1)

			for key in scheduled_date:
				description = frappe._("Reference: %s, Item Code: %s and Customer: %s") % \
					(self.name, d.item_code, self.customer)
				frappe.get_doc({
					"doctype": "Event",
					"owner": email_map.get(d.sales_person, self.owner),
					"subject": description,
					"description": description,
					"starts_on": cstr(key["scheduled_date"]) + " 10:00:00",
					"event_type": "Private",
					"ref_type": self.doctype,
					"ref_name": self.name
				}).insert(ignore_permissions=1)

		frappe.db.set(self, 'status', 'Submitted')

	def create_schedule_list(self, start_date, end_date, no_of_visit, sales_person):
		schedule_list = []
		start_date_copy = start_date
		date_diff = (getdate(end_date) - getdate(start_date)).days
		add_by = date_diff / no_of_visit

		for visit in range(cint(no_of_visit)):
			if (getdate(start_date_copy) < getdate(end_date)):
				start_date_copy = add_days(start_date_copy, add_by)
				if len(schedule_list) < no_of_visit:
					schedule_date = self.validate_schedule_date_for_holiday_list(getdate(start_date_copy),
						sales_person)
					if schedule_date > getdate(end_date):
						schedule_date = getdate(end_date)
					schedule_list.append(schedule_date)

		return schedule_list

	def validate_schedule_date_for_holiday_list(self, schedule_date, sales_person):
		validated = False

		employee = frappe.db.get_value("Sales Person", sales_person, "employee")
		if employee:
			holiday_list = get_holiday_list_for_employee(employee)
		else:
			holiday_list = frappe.db.get_value("Company", self.company, "default_holiday_list")

		holidays = frappe.db.sql_list('''select holiday_date from `tabHoliday` where parent=%s''', holiday_list)

		if not validated and holidays:

			# max iterations = len(holidays)
			for i in xrange(len(holidays)):
				if schedule_date in holidays:
					schedule_date = add_days(schedule_date, -1)
				else:
					validated = True
					break

		return schedule_date

	def validate_dates_with_periodicity(self):
		for d in self.get("items"):
			if d.start_date and d.end_date and d.periodicity and d.periodicity!="Random":
				date_diff = (getdate(d.end_date) - getdate(d.start_date)).days + 1
				days_in_period = {
					"Weekly": 7,
					"Monthly": 30,
					"Quarterly": 90,
					"Half Yearly": 180,
					"Yearly": 365
				}

				if date_diff < days_in_period[d.periodicity]:
					throw(_("Row {0}: To set {1} periodicity, difference between from and to date \
						must be greater than or equal to {2}")
						.format(d.idx, d.periodicity, days_in_period[d.periodicity]))

	def validate_maintenance_detail(self):
		if not self.get('items'):
			throw(_("Please enter Maintaince Details first"))

		for d in self.get('items'):
			if not d.item_code:
				throw(_("Please select item code"))
			elif not d.start_date or not d.end_date:
				throw(_("Please select Start Date and End Date for Item {0}".format(d.item_code)))
			elif not d.no_of_visits:
				throw(_("Please mention no of visits required"))
			elif not d.sales_person:
				throw(_("Please select Incharge Person's name"))

			if getdate(d.start_date) >= getdate(d.end_date):
				throw(_("Start date should be less than end date for Item {0}").format(d.item_code))

	def validate_sales_order(self):
		for d in self.get('items'):
			if d.sales_order:
				chk = frappe.db.sql("""select ms.name from `tabMaintenance Schedule` ms,
					`tabMaintenance Schedule Item` msi where msi.parent=ms.name and
					msi.sales_order=%s and ms.docstatus=1""", d.sales_order)
				if chk:
					throw(_("Maintenance Schedule {0} exists against {0}").format(chk[0][0], d.sales_order))

	def validate(self):
		self.validate_maintenance_detail()
		self.validate_dates_with_periodicity()
		self.validate_sales_order()

	def on_update(self):
		frappe.db.set(self, 'status', 'Draft')

	def update_amc_date(self, serial_nos, amc_expiry_date=None):
		for serial_no in serial_nos:
			serial_no_doc = frappe.get_doc("Serial No", serial_no)
			serial_no_doc.amc_expiry_date = amc_expiry_date
			serial_no_doc.save()

	def validate_serial_no(self, serial_nos, amc_start_date):
		for serial_no in serial_nos:
			sr_details = frappe.db.get_value("Serial No", serial_no,
				["warranty_expiry_date", "amc_expiry_date", "warehouse", "delivery_date"], as_dict=1)

			if not sr_details:
				frappe.throw(_("Serial No {0} not found").format(serial_no))

			if sr_details.warranty_expiry_date \
				and getdate(sr_details.warranty_expiry_date) >= getdate(amc_start_date):
				throw(_("Serial No {0} is under warranty upto {1}")
					.format(serial_no, sr_details.warranty_expiry_date))

			if sr_details.amc_expiry_date and getdate(sr_details.amc_expiry_date) >= getdate(amc_start_date):
				throw(_("Serial No {0} is under maintenance contract upto {1}")
					.format(serial_no, sr_details.amc_start_date))

			if not sr_details.warehouse and sr_details.delivery_date and \
				getdate(sr_details.delivery_date) >= getdate(amc_start_date):
					throw(_("Maintenance start date can not be before delivery date for Serial No {0}")
						.format(serial_no))

	def validate_schedule(self):
		item_lst1 =[]
		item_lst2 =[]
		for d in self.get('items'):
			if d.item_code not in item_lst1:
				item_lst1.append(d.item_code)

		for m in self.get('schedules'):
			if m.item_code not in item_lst2:
				item_lst2.append(m.item_code)

		if len(item_lst1) != len(item_lst2):
			throw(_("Maintenance Schedule is not generated for all the items. Please click on 'Generate Schedule'"))
		else:
			for x in item_lst1:
				if x not in item_lst2:
					throw(_("Please click on 'Generate Schedule'"))

	def check_serial_no_added(self):
		serial_present =[]
		for d in self.get('items'):
			if d.serial_no:
				serial_present.append(d.item_code)

		for m in self.get('schedules'):
			if serial_present:
				if m.item_code in serial_present and not m.serial_no:
					throw(_("Please click on 'Generate Schedule' to fetch Serial No added for Item {0}").format(m.item_code))

	def on_cancel(self):
		for d in self.get('items'):
			if d.serial_no:
				serial_nos = get_valid_serial_nos(d.serial_no)
				self.update_amc_date(serial_nos)
		frappe.db.set(self, 'status', 'Cancelled')
		delete_events(self.doctype, self.name)

	def on_trash(self):
		delete_events(self.doctype, self.name)

@frappe.whitelist()
def make_maintenance_visit(source_name, target_doc=None):
	from frappe.model.mapper import get_mapped_doc

	def update_status(source, target, parent):
		target.maintenance_type = "Scheduled"

	doclist = get_mapped_doc("Maintenance Schedule", source_name, {
		"Maintenance Schedule": {
			"doctype": "Maintenance Visit",
			"field_map": {
				"name": "maintenance_schedule"
			},
			"validation": {
				"docstatus": ["=", 1]
			},
			"postprocess": update_status
		},
		"Maintenance Schedule Item": {
			"doctype": "Maintenance Visit Purpose",
			"field_map": {
				"parent": "prevdoc_docname",
				"parenttype": "prevdoc_doctype",
				"sales_person": "service_person"
			}
		}
	}, target_doc)

	return doclist
<commit_msg>Minor fix in maintenance schedule<commit_after># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe

from frappe.utils import add_days, getdate, cint, cstr

from frappe import throw, _
from erpnext.utilities.transaction_base import TransactionBase, delete_events
from erpnext.stock.utils import get_valid_serial_nos
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee

class MaintenanceSchedule(TransactionBase):
	def generate_schedule(self):
		self.set('schedules', [])
		frappe.db.sql("""delete from `tabMaintenance Schedule Detail`
			where parent=%s""", (self.name))
		count = 1
		for d in self.get('items'):
			self.validate_maintenance_detail()
			s_list = []
			s_list = self.create_schedule_list(d.start_date, d.end_date, d.no_of_visits, d.sales_person)
			for i in range(d.no_of_visits):
				child = self.append('schedules')
				child.item_code = d.item_code
				child.item_name = d.item_name
				child.scheduled_date = s_list[i].strftime('%Y-%m-%d')
				if d.serial_no:
					child.serial_no = d.serial_no
				child.idx = count
				count = count + 1
				child.sales_person = d.sales_person

		self.save()

	def on_submit(self):
		if not self.get('schedules'):
			throw(_("Please click on 'Generate Schedule' to get schedule"))
		self.check_serial_no_added()
		self.validate_schedule()

		email_map = {}
		for d in self.get('items'):
			if d.serial_no:
				serial_nos = get_valid_serial_nos(d.serial_no)
				self.validate_serial_no(serial_nos, d.start_date)
				self.update_amc_date(serial_nos, d.end_date)

			no_email_sp = []
			if d.sales_person not in email_map:
				sp = frappe.get_doc("Sales Person", d.sales_person)
				try:
					email_map[d.sales_person] = sp.get_email_id()
				except frappe.ValidationError:
					no_email_sp.append(d.sales_person)

			if no_email_sp:
				frappe.msgprint(
					frappe._("Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}").format(
						self.owner, "
" + "
".join(no_email_sp)
				))

			scheduled_date = frappe.db.sql("""select scheduled_date from
				`tabMaintenance Schedule Detail` where sales_person=%s and item_code=%s and
				parent=%s""", (d.sales_person, d.item_code, self.name), as_dict=1)

			for key in scheduled_date:
				description = frappe._("Reference: %s, Item Code: %s and Customer: %s") % \
					(self.name, d.item_code, self.customer)
				frappe.get_doc({
					"doctype": "Event",
					"owner": email_map.get(d.sales_person, self.owner),
					"subject": description,
					"description": description,
					"starts_on": cstr(key["scheduled_date"]) + " 10:00:00",
					"event_type": "Private",
					"ref_type": self.doctype,
					"ref_name": self.name
				}).insert(ignore_permissions=1)

		frappe.db.set(self, 'status', 'Submitted')

	def create_schedule_list(self, start_date, end_date, no_of_visit, sales_person):
		schedule_list = []
		start_date_copy = start_date
		date_diff = (getdate(end_date) - getdate(start_date)).days
		add_by = date_diff / no_of_visit

		for visit in range(cint(no_of_visit)):
			if (getdate(start_date_copy) < getdate(end_date)):
				start_date_copy = add_days(start_date_copy, add_by)
				if len(schedule_list) < no_of_visit:
					schedule_date = self.validate_schedule_date_for_holiday_list(getdate(start_date_copy),
						sales_person)
					if schedule_date > getdate(end_date):
						schedule_date = getdate(end_date)
					schedule_list.append(schedule_date)

		return schedule_list

	def validate_schedule_date_for_holiday_list(self, schedule_date, sales_person):
		validated = False

		employee = frappe.db.get_value("Sales Person", sales_person, "employee")
		if employee:
			holiday_list = get_holiday_list_for_employee(employee)
		else:
			holiday_list = frappe.db.get_value("Company", self.company, "default_holiday_list")

		holidays = frappe.db.sql_list('''select holiday_date from `tabHoliday` where parent=%s''', holiday_list)

		if not validated and holidays:

			# max iterations = len(holidays)
			for i in xrange(len(holidays)):
				if schedule_date in holidays:
					schedule_date = add_days(schedule_date, -1)
				else:
					validated = True
					break

		return schedule_date

	def validate_dates_with_periodicity(self):
		for d in self.get("items"):
			if d.start_date and d.end_date and d.periodicity and d.periodicity!="Random":
				date_diff = (getdate(d.end_date) - getdate(d.start_date)).days + 1
				days_in_period = {
					"Weekly": 7,
					"Monthly": 30,
					"Quarterly": 90,
					"Half Yearly": 180,
					"Yearly": 365
				}

				if date_diff < days_in_period[d.periodicity]:
					throw(_("Row {0}: To set {1} periodicity, difference between from and to date \
						must be greater than or equal to {2}")
						.format(d.idx, d.periodicity, days_in_period[d.periodicity]))

	def validate_maintenance_detail(self):
		if not self.get('items'):
			throw(_("Please enter Maintaince Details first"))

		for d in self.get('items'):
			if not d.item_code:
				throw(_("Please select item code"))
			elif not d.start_date or not d.end_date:
				throw(_("Please select Start Date and End Date for Item {0}".format(d.item_code)))
			elif not d.no_of_visits:
				throw(_("Please mention no of visits required"))
			elif not d.sales_person:
				throw(_("Please select Incharge Person's name"))

			if getdate(d.start_date) >= getdate(d.end_date):
				throw(_("Start date should be less than end date for Item {0}").format(d.item_code))

	def validate_sales_order(self):
		for d in self.get('items'):
			if d.sales_order:
				chk = frappe.db.sql("""select ms.name from `tabMaintenance Schedule` ms,
					`tabMaintenance Schedule Item` msi where msi.parent=ms.name and
					msi.sales_order=%s and ms.docstatus=1""", d.sales_order)
				if chk:
					throw(_("Maintenance Schedule {0} exists against {0}").format(chk[0][0], d.sales_order))

	def validate(self):
		self.validate_maintenance_detail()
		self.validate_dates_with_periodicity()
		self.validate_sales_order()

	def on_update(self):
		frappe.db.set(self, 'status', 'Draft')

	def update_amc_date(self, serial_nos, amc_expiry_date=None):
		for serial_no in serial_nos:
			serial_no_doc = frappe.get_doc("Serial No", serial_no)
			serial_no_doc.amc_expiry_date = amc_expiry_date
			serial_no_doc.save()

	def validate_serial_no(self, serial_nos, amc_start_date):
		for serial_no in serial_nos:
			sr_details = frappe.db.get_value("Serial No", serial_no,
				["warranty_expiry_date", "amc_expiry_date", "warehouse", "delivery_date"], as_dict=1)

			if not sr_details:
				frappe.throw(_("Serial No {0} not found").format(serial_no))

			if sr_details.warranty_expiry_date \
				and getdate(sr_details.warranty_expiry_date) >= getdate(amc_start_date):
				throw(_("Serial No {0} is under warranty upto {1}")
					.format(serial_no, sr_details.warranty_expiry_date))

			if sr_details.amc_expiry_date and getdate(sr_details.amc_expiry_date) >= getdate(amc_start_date):
				throw(_("Serial No {0} is under maintenance contract upto {1}")
					.format(serial_no, sr_details.amc_start_date))

			if not sr_details.warehouse and sr_details.delivery_date and \
				getdate(sr_details.delivery_date) >= getdate(amc_start_date):
					throw(_("Maintenance start date can not be before delivery date for Serial No {0}")
						.format(serial_no))

	def validate_schedule(self):
		item_lst1 =[]
		item_lst2 =[]
		for d in self.get('items'):
			if d.item_code not in item_lst1:
				item_lst1.append(d.item_code)

		for m in self.get('schedules'):
			if m.item_code not in item_lst2:
				item_lst2.append(m.item_code)

		if len(item_lst1) != len(item_lst2):
			throw(_("Maintenance Schedule is not generated for all the items. Please click on 'Generate Schedule'"))
		else:
			for x in item_lst1:
				if x not in item_lst2:
					throw(_("Please click on 'Generate Schedule'"))

	def check_serial_no_added(self):
		serial_present =[]
		for d in self.get('items'):
			if d.serial_no:
				serial_present.append(d.item_code)

		for m in self.get('schedules'):
			if serial_present:
				if m.item_code in serial_present and not m.serial_no:
					throw(_("Please click on 'Generate Schedule' to fetch Serial No added for Item {0}").format(m.item_code))

	def on_cancel(self):
		for d in self.get('items'):
			if d.serial_no:
				serial_nos = get_valid_serial_nos(d.serial_no)
				self.update_amc_date(serial_nos)
		frappe.db.set(self, 'status', 'Cancelled')
		delete_events(self.doctype, self.name)

	def on_trash(self):
		delete_events(self.doctype, self.name)

@frappe.whitelist()
def make_maintenance_visit(source_name, target_doc=None):
	from frappe.model.mapper import get_mapped_doc

	def update_status(source, target, parent):
		target.maintenance_type = "Scheduled"

	doclist = get_mapped_doc("Maintenance Schedule", source_name, {
		"Maintenance Schedule": {
			"doctype": "Maintenance Visit",
			"field_map": {
				"name": "maintenance_schedule"
			},
			"validation": {
				"docstatus": ["=", 1]
			},
			"postprocess": update_status
		},
		"Maintenance Schedule Item": {
			"doctype": "Maintenance Visit Purpose",
			"field_map": {
				"parent": "prevdoc_docname",
				"parenttype": "prevdoc_doctype",
				"sales_person": "service_person"
			}
		}
	}, target_doc)

	return doclist
<|endoftext|>


<commit_before>import cv2
import numpy
import math

from numpy.random import random_integers
from scipy.ndimage import interpolation
from scipy.ndimage.filters import gaussian_filter

def prepare_test_image(image, width ,resize_shape):
    """
    This function normalizes an an already padded image and flattens it into a
    row vector
    :param image: a numpy array
    :param resize_shape: a tuple denoting the shape of the padded image
    :return : a 1-D array
    """

    # resizing the image
    #resized_image = resize_img(cropped_image, resize_shape)
    resized_img = width_normalization(image, width, resize_shape)

    # deskew
    #deskewed_image = deskew(resized_image, resize_shape)

    # negate the image and normalize its values to fit in the range [0,1]
    norm_image = numpy.asarray(255-resized_img, dtype=numpy.float32) / 255.

    # Flatten the image to a 1-D vector and return
    return norm_image.reshape(1, resize_shape[0] * resize_shape[1])

def do_cropping(image):
    """
    This method will crop the image using the outermost detectable contour

    :param image: a numpy array
    """

    # do thresholding
    ret,thresh = cv2.threshold(255-image,127,255,0)

    # find contours
    img, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,
                                                  cv2.CHAIN_APPROX_SIMPLE)

    # find the index of contour with maximum area
    try:
        max_index = numpy.argmax(numpy.asarray([len(c) for c in contours]))
    except ValueError:
        return image

    # approximate the contours
    approx = cv2.approxPolyDP(contours[max_index], 3, True)

    # find the cropping co-ordinates
    crop_rect = cv2.boundingRect(approx)

    # return cropped image
    cropped_img = image[crop_rect[0]:crop_rect[0]+crop_rect[3],\
                        crop_rect[1]:crop_rect[1]+crop_rect[2]]

    return cropped_img

def deskew(image, image_shape, negated=False):
    """
    This method deskwes an image using moments
    :param image: a numpy nd array input image
    :param image_shape: a tuple denoting the image`s shape
    :param negated: a boolean flag telling  whether the input image is a negated one

    :returns: a numpy nd array deskewd image
    """

    # negate the image
    if not negated:
        image = 255-image

    # calculate the moments of the image
    m = cv2.moments(image)
    if abs(m['mu02']) < 1e-2:
        return image.copy()

    # caclulating the skew
    skew = m['mu11']/m['mu02']
    M = numpy.float32([[1, skew, -0.5*image_shape[0]*skew], [0,1,0]])
    img = cv2.warpAffine(image, M, image_shape, flags=cv2.WARP_INVERSE_MAP|cv2.INTER_LINEAR)

    return img

def resize_img(image, target_shape, value=255, min_padding=5):
    """
    This method adds padding to the image and makes it to a nxn array,
    without losing the aspect ratio

    :param image: a numpy array
    :param target_shape: the dimensions to which the image needs to be resized
    :param min_padding: minimum padding that to be added
    :param value: the value of the padding area
    :returns :  a padded image
    """

    # Getting the image dimensions
    image_width = image.shape[1]
    image_height = image.shape[0]

    # Getting the target dimensions
    target_width = target_shape[1]
    target_height = target_shape[0]

    # Add padding
    max_index = numpy.argmax([image_height, image_width])
    if max_index == 0:
        padded_img = cv2.copyMakeBorder(image, min_padding, min_padding,
                                        (image_height + min_padding - image_width)/2,
                                        (image_height + min_padding - image_width)/2,
                                        cv2.BORDER_CONSTANT, value=value)
    else:
        padded_img = cv2.copyMakeBorder(image,
                                        (image_width + min_padding - image_height)/2,
                                        (image_width + min_padding - image_height)/2,
                                        min_padding, min_padding, cv2.BORDER_CONSTANT,
                                        value=value)

    return cv2.resize(padded_img, target_shape)

def elastic_transform(image, kernel_dim=13, sigma=6, alpha=36, negated=False):
    """
    This method performs elastic transformations on an image by convolving
    with a gaussian kernel.

    :param image: a numpy nd array
    :kernel_dim: dimension(1-D) of the gaussian kernel
    :param sigma: standard deviation of the kernel
    :param alpha: a multiplicative factor for image after convolution
    :param negated: a flag indicating whether the image is negated or not

    :returns: a nd array transformed image
    """
    # check if the image is a negated one
    if not negated:
        image = 255-image

    # create an empty image
    result = numpy.zeros(image.shape)

    # create random displacement fields
    displacement_field_x = numpy.array([[random_integers(-1, 1) for x in xrange(kernel_dim)] \
                            for y in xrange(kernel_dim)]) * alpha
    displacement_field_y = numpy.array([[random_integers(-1, 1) for x in xrange(kernel_dim)] \
                            for y in xrange(kernel_dim)]) * alpha

    # convolve the fields with the gaussian kernel
    displacement_field_x = gaussian_filter(displacement_field_x, sigma)
    displacement_field_y = gaussian_filter(displacement_field_y, sigma)

    # make the distortrd image by averaging each pixel value to the neighbouring
    # four pixels based on displacement fields

    for row in xrange(image.shape[1]):
        for col in xrange(image.shape[0]):
            low_ii = row + int(math.floor(displacement_field_y[row, col]))
            high_ii = row + int(math.ceil(displacement_field_y[row, col]))

            low_jj = col + int(math.floor(displacement_field_y[row, col]))
            high_jj = col + int(math.ceil(displacement_field_y[row, col]))

            if low_ii < 0 or low_jj < 0 or high_ii >= image.shape[1] -1 \
               or high_jj >= image.shape[0] - 1:
                continue

            res = image[low_ii, low_jj]/4 + image[low_ii, high_jj]/4 + image[high_ii, low_jj]/4 + image[high_ii, high_jj]/4

            result[row, col] = res

    return result

def width_normalization(image, width, target_shape):
    """
    This method creates a width normalised 1-d vector of an image

    :param image: a nd array denoting the image
    :param width: the width o which the vector shoul be normalized
    :param target_shape: a tuple denoting the output dims

    :returns: a nd array width normalized image
    """

    # crop the number bounding box
    cropped_img = do_cropping(image)

    # width normalization
    width_normalized_img = cv2.resize(cropped_img, (width, cropped_img.shape[1]))

    # add padding and resize to the specified shape
    resized_image = resize_img(width_normalized_img, target_shape)

    # return the width normalized image
    return resized_image

<commit_msg>Edited some comments<commit_after>import cv2
import numpy
import math

from numpy.random import random_integers
from scipy.ndimage import interpolation
from scipy.ndimage.filters import gaussian_filter

def prepare_test_image(image, width ,resize_shape):
    """
    This function normalizes a test image and flattens it into a
    row vector
    :param image: a numpy array
    :param width: width for width normalization
    :param resize_shape: a tuple denoting the shape of the padded image
    :return : a 1-D array
    """

    # resizing the image
    resized_img = width_normalization(image, width, resize_shape)

    # deskew
    #deskewed_image = deskew(resized_image, resize_shape)

    # negate the image and normalize its values to fit in the range [0,1]
    norm_image = numpy.asarray(255-resized_img, dtype=numpy.float32) / 255.

    # Flatten the image to a 1-D vector and return
    return norm_image.reshape(1, resize_shape[0] * resize_shape[1])

def do_cropping(image):
    """
    This method will crop the image using the outermost detectable contour

    :param image: a numpy array
    """

    # do thresholding
    ret,thresh = cv2.threshold(255-image,127,255,0)

    # find contours
    img, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,
                                                  cv2.CHAIN_APPROX_SIMPLE)

    # find the index of contour with maximum area
    try:
        max_index = numpy.argmax(numpy.asarray([len(c) for c in contours]))
    except ValueError:
        return image

    # approximate the contours
    approx = cv2.approxPolyDP(contours[max_index], 3, True)

    # find the cropping co-ordinates
    crop_rect = cv2.boundingRect(approx)

    # return cropped image
    cropped_img = image[crop_rect[0]:crop_rect[0]+crop_rect[3],\
                        crop_rect[1]:crop_rect[1]+crop_rect[2]]

    return cropped_img

def deskew(image, image_shape, negated=False):
    """
    This method deskwes an image using moments
    :param image: a numpy nd array input image
    :param image_shape: a tuple denoting the image`s shape
    :param negated: a boolean flag telling  whether the input image is a negated one

    :returns: a numpy nd array deskewd image
    """

    # negate the image
    if not negated:
        image = 255-image

    # calculate the moments of the image
    m = cv2.moments(image)
    if abs(m['mu02']) < 1e-2:
        return image.copy()

    # caclulating the skew
    skew = m['mu11']/m['mu02']
    M = numpy.float32([[1, skew, -0.5*image_shape[0]*skew], [0,1,0]])
    img = cv2.warpAffine(image, M, image_shape, flags=cv2.WARP_INVERSE_MAP|cv2.INTER_LINEAR)

    return img

def resize_img(image, target_shape, value=255, min_padding=5):
    """
    This method adds padding to the image and makes it to a nxn array,
    without losing the aspect ratio

    :param image: a numpy array
    :param target_shape: the dimensions to which the image needs to be resized
    :param min_padding: minimum padding that to be added
    :param value: the value of the padding area
    :returns :  a padded image
    """

    # Getting the image dimensions
    image_width = image.shape[1]
    image_height = image.shape[0]

    # Getting the target dimensions
    target_width = target_shape[1]
    target_height = target_shape[0]

    # Add padding
    max_index = numpy.argmax([image_height, image_width])
    if max_index == 0:
        padded_img = cv2.copyMakeBorder(image, min_padding, min_padding,
                                        (image_height + min_padding - image_width)/2,
                                        (image_height + min_padding - image_width)/2,
                                        cv2.BORDER_CONSTANT, value=value)
    else:
        padded_img = cv2.copyMakeBorder(image,
                                        (image_width + min_padding - image_height)/2,
                                        (image_width + min_padding - image_height)/2,
                                        min_padding, min_padding, cv2.BORDER_CONSTANT,
                                        value=value)

    return cv2.resize(padded_img, target_shape)

def elastic_transform(image, kernel_dim=13, sigma=6, alpha=36, negated=False):
    """
    This method performs elastic transformations on an image by convolving
    with a gaussian kernel.

    :param image: a numpy nd array
    :kernel_dim: dimension(1-D) of the gaussian kernel
    :param sigma: standard deviation of the kernel
    :param alpha: a multiplicative factor for image after convolution
    :param negated: a flag indicating whether the image is negated or not

    :returns: a nd array transformed image
    """
    # check if the image is a negated one
    if not negated:
        image = 255-image

    # create an empty image
    result = numpy.zeros(image.shape)

    # create random displacement fields
    displacement_field_x = numpy.array([[random_integers(-1, 1) for x in xrange(kernel_dim)] \
                            for y in xrange(kernel_dim)]) * alpha
    displacement_field_y = numpy.array([[random_integers(-1, 1) for x in xrange(kernel_dim)] \
                            for y in xrange(kernel_dim)]) * alpha

    # convolve the fields with the gaussian kernel
    displacement_field_x = gaussian_filter(displacement_field_x, sigma)
    displacement_field_y = gaussian_filter(displacement_field_y, sigma)

    # make the distortrd image by averaging each pixel value to the neighbouring
    # four pixels based on displacement fields

    for row in xrange(image.shape[1]):
        for col in xrange(image.shape[0]):
            low_ii = row + int(math.floor(displacement_field_y[row, col]))
            high_ii = row + int(math.ceil(displacement_field_y[row, col]))

            low_jj = col + int(math.floor(displacement_field_y[row, col]))
            high_jj = col + int(math.ceil(displacement_field_y[row, col]))

            if low_ii < 0 or low_jj < 0 or high_ii >= image.shape[1] -1 \
               or high_jj >= image.shape[0] - 1:
                continue

            res = image[low_ii, low_jj]/4 + image[low_ii, high_jj]/4 + \
                    image[high_ii, low_jj]/4 + image[high_ii, high_jj]/4

            result[row, col] = res

    return result

def width_normalization(image, width, target_shape):
    """
    This method creates a width normalised 1-d vector of an image

    :param image: a nd array denoting the image
    :param width: the width o which the vector shoul be normalized
    :param target_shape: a tuple denoting the output dims

    :returns: a nd array width normalized image
    """

    # crop the number bounding box
    cropped_img = do_cropping(image)

    # width normalization
    width_normalized_img = cv2.resize(cropped_img, (width, cropped_img.shape[1]))

    # add padding and resize to the specified shape
    resized_image = resize_img(width_normalized_img, target_shape)

    # return the width normalized image
    return resized_image

<|endoftext|>


<commit_before>from simplejson import dumps
from getpass import getuser

from .base.base_drmaa import BaseDrmaaManager
from .util.sudo import sudo_popen

from logging import getLogger
log = getLogger(__name__)

DEFAULT_CHOWN_WORKING_DIRECTORY_SCRIPT = "scripts/chown_working_directory.bash"
DEFAULT_DRMAA_KILL_SCRIPT = "scripts/drmaa_kill.bash"
DEFAULT_DRMAA_LAUNCH_SCRIPT = "scripts/drmaa_launch.bash"

class ExternalDrmaaQueueManager(BaseDrmaaManager):
    """
    DRMAA backed queue manager.
    """
    manager_type = "queued_external_drmaa"

    def __init__(self, name, app, **kwds):
        super(ExternalDrmaaQueueManager, self).__init__(name, app, **kwds)
        self.chown_working_directory_script = kwds.get('chown_working_directory_script', DEFAULT_CHOWN_WORKING_DIRECTORY_SCRIPT)
        self.drmaa_kill_script = kwds.get('drmaa_kill_script', DEFAULT_DRMAA_KILL_SCRIPT)
        self.drmaa_launch_script = kwds.get('drmaa_launch_script', DEFAULT_DRMAA_LAUNCH_SCRIPT)
        self.production = kwds.get('production', "true").lower() != "false"
        self.reclaimed = {}
        self.user_map = {}

    def launch(self, job_id, command_line, submit_params={}):
        self._check_execution_with_tool_file(job_id, command_line)
        attributes = self._build_template_attributes(job_id, command_line)
        job_attributes_file = self._write_job_file(job_id, 'jt.json', dumps(attributes))
        user = submit_params.get('user', None)
        log.info("Submit as user %s" % user)
        if not user:
            raise Exception("Must specify user submit parameter with this manager.")
        self.__change_ownership(job_id, user)
        external_id = self.__launch(job_attributes_file, user).strip()
        self.user_map[external_id] = user
        self._register_external_id(job_id, external_id)

    def _kill_external(self, external_id):
        user = self.user_map[external_id]
        self.__sudo(self.drmaa_kill_script, "--external_id", external_id, user=user)

    def get_status(self, job_id):
        external_id = self._external_id(job_id)
        if not external_id:
            raise KeyError("Failed to find external id for job_id %s" % job_id)
        status = super(ExternalDrmaaQueueManager, self)._get_status_external(external_id)
        if status == "complete" and job_id not in self.reclaimed:
            self.reclaimed[job_id] = True
            self.__change_ownership(job_id, getuser())
        return status

    def __launch(self, job_attributes, user):
        return self.__sudo(self.drmaa_launch_script, "--job_attributes", str(job_attributes), user=user)

    def __change_ownership(self, job_id, username):
        cmds = [self.chown_working_directory_script, "--user", str(username)]
        if self.production:
            cmds.extend(["--job_id", job_id])
        else:
            # In testing, the loading working directory from server.ini doesn't
            # work. Need to reimagine how to securely map job_id to working
            # direcotry between test cases and production.
            cmds.extend(["--job_directory", str(self._job_directory(job_id).path)])
        # TODO: Verify ownership change.
        self.__sudo(*cmds)

    def __sudo(self, *cmds, **kwargs):
        print cmds
        p = sudo_popen(*cmds, **kwargs)
        stdout, stderr = p.communicate()
        assert p.returncode == 0, "%s, %s" % (stdout, stderr)
        return stdout
<commit_msg>Remove stray (and invalid for Python 3) print statement in lwr/managers/queued_external_drmaa.py.<commit_after>from simplejson import dumps
from getpass import getuser

from .base.base_drmaa import BaseDrmaaManager
from .util.sudo import sudo_popen

from logging import getLogger
log = getLogger(__name__)

DEFAULT_CHOWN_WORKING_DIRECTORY_SCRIPT = "scripts/chown_working_directory.bash"
DEFAULT_DRMAA_KILL_SCRIPT = "scripts/drmaa_kill.bash"
DEFAULT_DRMAA_LAUNCH_SCRIPT = "scripts/drmaa_launch.bash"

class ExternalDrmaaQueueManager(BaseDrmaaManager):
    """
    DRMAA backed queue manager.
    """
    manager_type = "queued_external_drmaa"

    def __init__(self, name, app, **kwds):
        super(ExternalDrmaaQueueManager, self).__init__(name, app, **kwds)
        self.chown_working_directory_script = kwds.get('chown_working_directory_script', DEFAULT_CHOWN_WORKING_DIRECTORY_SCRIPT)
        self.drmaa_kill_script = kwds.get('drmaa_kill_script', DEFAULT_DRMAA_KILL_SCRIPT)
        self.drmaa_launch_script = kwds.get('drmaa_launch_script', DEFAULT_DRMAA_LAUNCH_SCRIPT)
        self.production = kwds.get('production', "true").lower() != "false"
        self.reclaimed = {}
        self.user_map = {}

    def launch(self, job_id, command_line, submit_params={}):
        self._check_execution_with_tool_file(job_id, command_line)
        attributes = self._build_template_attributes(job_id, command_line)
        job_attributes_file = self._write_job_file(job_id, 'jt.json', dumps(attributes))
        user = submit_params.get('user', None)
        log.info("Submit as user %s" % user)
        if not user:
            raise Exception("Must specify user submit parameter with this manager.")
        self.__change_ownership(job_id, user)
        external_id = self.__launch(job_attributes_file, user).strip()
        self.user_map[external_id] = user
        self._register_external_id(job_id, external_id)

    def _kill_external(self, external_id):
        user = self.user_map[external_id]
        self.__sudo(self.drmaa_kill_script, "--external_id", external_id, user=user)

    def get_status(self, job_id):
        external_id = self._external_id(job_id)
        if not external_id:
            raise KeyError("Failed to find external id for job_id %s" % job_id)
        status = super(ExternalDrmaaQueueManager, self)._get_status_external(external_id)
        if status == "complete" and job_id not in self.reclaimed:
            self.reclaimed[job_id] = True
            self.__change_ownership(job_id, getuser())
        return status

    def __launch(self, job_attributes, user):
        return self.__sudo(self.drmaa_launch_script, "--job_attributes", str(job_attributes), user=user)

    def __change_ownership(self, job_id, username):
        cmds = [self.chown_working_directory_script, "--user", str(username)]
        if self.production:
            cmds.extend(["--job_id", job_id])
        else:
            # In testing, the loading working directory from server.ini doesn't
            # work. Need to reimagine how to securely map job_id to working
            # direcotry between test cases and production.
            cmds.extend(["--job_directory", str(self._job_directory(job_id).path)])
        # TODO: Verify ownership change.
        self.__sudo(*cmds)

    def __sudo(self, *cmds, **kwargs):
        p = sudo_popen(*cmds, **kwargs)
        stdout, stderr = p.communicate()
        assert p.returncode == 0, "%s, %s" % (stdout, stderr)
        return stdout
<|endoftext|>


<commit_before>import csv, logging, os, shutil, time
import mod_conf, mod_cdr_decode

from datetime import datetime
from elasticsearch import Elasticsearch

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

#Logger Console Handler
ch = logging.StreamHandler() #StreamHandler logs to console
ch.setLevel(logging.DEBUG)
ch_format = logging.Formatter('%(asctime)s - %(message)s')
ch.setFormatter(ch_format)
logger.addHandler(ch)

#Logger File Handler
fh = logging.FileHandler('/var/log/cdr_parser/{0}.log'.format(__name__))
fh.setLevel(logging.INFO)
fh_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)-8s - %(message)s')
fh.setFormatter(fh_format)
logger.addHandler(fh)

def initial_program_setup():
  print "initial_program_setup"

def do_main_program():

  # by default connect to localhost:9200
  es = Elasticsearch()

  for file in os.listdir(mod_conf.cdr_path):
    # Get pathes from config file
    src_file = os.path.join(mod_conf.cdr_path, file)
    dest_file = os.path.join(mod_conf.archive_path,file)

    logger.debug("src_file = %s" % src_file)
    logger.debug("dest_file = %s" % dest_file)

    # Check for configured type, if none use filename
    if mod_conf.es_type == "":
      es_type = file
    else:
      es_type = mod_conf.es_type

    logger.debug("es_type = %s" % es_type)

    file_moved = True
    try:
      shutil.move(src_file, mod_conf.archive_path)
    except:
      logger.warning("Error moving CDR file to archive.  Will retry.")
      file_moved = False

    time.sleep(.5)

    if os.access(dest_file, os.W_OK) and file_moved:
      logger.debug("CDR successfully moved to archive.")
      # Open CDR Log File
      csv_file = open(dest_file, 'rb')
      csv_read = csv.reader(csv_file, delimiter=',', quotechar='"')

      # Read CDR header row
      csv_keys = next(csv_read)

      # Skip CDR types row
      csv_types = next(csv_read)

      # Process actual CDR rows
      for csv_line in csv_read:
        # Combine headers with data
        csv_zip = zip(csv_keys, csv_line)

        # Check for empty lines
        if csv_zip:

          es_body = {}

          # Call Sequence Variables
          origNum = ""
          finNum = ""

          for csv_data in csv_zip:
            # Decode cdrRecordType
            if csv_data[0] == "cdrRecordType":
              es_body[csv_data[0]] = mod_cdr_decode.decode_RecordType(val=csv_data[1])
              # Check for configured type, if none use cdr/cmr-YYYY.MM.DD
              if mod_conf.es_index == "":
                if csv_data[1] == "1":
                  es_index = "cdr-%s" % datetime.utcnow().strftime("%Y.%m.%d")
                elif csv_data[1] == "2":
                  es_index = "cmr-%s" % datetime.utcnow().strftime("%Y.%m.%d")
                else:
                  es_index = "index_err"
              else:
                 es_index = mod_conf.es_index
            # Decode dateTimeStamp
            elif csv_data[0] == "dateTimeStamp":
              es_body[csv_data[0]] = mod_cdr_decode.decode_Time(val=csv_data[1])
              # Build @timestamp
              es_body['@timestamp'] = mod_cdr_decode.decode_Time(val=csv_data[1])
            # Decode dateTimeOrigination
            elif csv_data[0] == "dateTimeOrigination":
              es_body[csv_data[0]] = mod_cdr_decode.decode_Time(val=csv_data[1])
              # Build @timestamp
              es_body['@timestamp'] = mod_cdr_decode.decode_Time(val=csv_data[1])
            # Decode origIpAddr
            elif csv_data[0] == "origIpAddr":
              es_body[csv_data[0]] = mod_cdr_decode.decode_IP(val=csv_data[1])
            # Decode origCause_location
            elif csv_data[0] == "origCause_location":
              es_body[csv_data[0]] = mod_cdr_decode.decode_TermCauseCode(val=csv_data[1])
            # Decode origCause_value
            elif csv_data[0] == "origCause_value":
              es_body[csv_data[0]] = mod_cdr_decode.decode_TermCauseCode(val=csv_data[1])
            # Decode origPrecedenceLevel
            elif csv_data[0] == "origPrecedenceLevel":
              es_body[csv_data[0]] = mod_cdr_decode.decode_PrecedenceLevel(val=csv_data[1])
            # Decode origMediaTransportAddress_IP
            elif csv_data[0] == "origMediaTransportAddress_IP":
              es_body[csv_data[0]] = mod_cdr_decode.decode_IP(val=csv_data[1])
            # Decode origMediaCap_payloadCapability
            elif csv_data[0] == "origMediaCap_payloadCapability":
              es_body[csv_data[0]] = mod_cdr_decode.decode_CodecType(val=csv_data[1])
            # Decode origVideoCap_Codec
            elif csv_data[0] == "origVideoCap_Codec":
              es_body[csv_data[0]] = mod_cdr_decode.decode_CodecType(val=csv_data[1])
            # Decode origVideoCap_Resolution
            elif csv_data[0] == "origVideoCap_Resolution":
              es_body[csv_data[0]] = mod_cdr_decode.decode_VideoRes(val=csv_data[1])
            # Decode origRSVPAudioStat
            elif csv_data[0] == "origRSVPAudioStat":
              es_body[csv_data[0]] = mod_cdr_decode.decode_RSVPStat(val=csv_data[1])
            # Decode origRSVPVideoStat
            elif csv_data[0] == "origRSVPVideoStat":
              es_body[csv_data[0]] = mod_cdr_decode.decode_RSVPStat(val=csv_data[1])
            # Decode destIpAddr
            elif csv_data[0] == "destIpAddr":
              es_body[csv_data[0]] = mod_cdr_decode.decode_IP(val=csv_data[1])
            # Decode destCause_location
            elif csv_data[0] == "destCause_location":
              es_body[csv_data[0]] = mod_cdr_decode.decode_TermCauseCode(val=csv_data[1])
            # Decode destCause_value
            elif csv_data[0] == "destCause_value":
              es_body[csv_data[0]] = mod_cdr_decode.decode_TermCauseCode(val=csv_data[1])
            # Decode destPrecedenceLevel
            elif csv_data[0] == "destCause_value":
              es_body[csv_data[0]] = mod_cdr_decode.decode_PrecedenceLevel(val=csv_data[1])
            # Decode destMediaTransportAddress_IP
            elif csv_data[0] == "destMediaTransportAddress_IP":
              es_body[csv_data[0]] = mod_cdr_decode.decode_IP(val=csv_data[1])
            # Decode destMediaCap_payloadCapability
            elif csv_data[0] == "destMediaCap_payloadCapability":
              es_body[csv_data[0]] = mod_cdr_decode.decode_CodecType(val=csv_data[1])
            # Decode destVideoCap_Codec
            elif csv_data[0] == "destVideoCap_Codec":
              es_body[csv_data[0]] = mod_cdr_decode.decode_CodecType(val=csv_data[1])
            # Decode destVideoCap_Resolution
            elif csv_data[0] == "destVideoCap_Resolution":
              es_body[csv_data[0]] = mod_cdr_decode.decode_VideoRes(val=csv_data[1])
            # Decode destVideoTransportAddressdest_IP
            elif csv_data[0] == "destVideoTransportAddress_IP":
              es_body[csv_data[0]] = mod_cdr_decode.decode_IP(val=csv_data[1])
            # Decode destRSVPAudioStat
            elif csv_data[0] == "destRSVPAudioStat":
              es_body[csv_data[0]] = mod_cdr_decode.decode_RSVPStat(val=csv_data[1])
            # Decode destRSVPVideoStat
            elif csv_data[0] == "destRSVPVideoStat":
              es_body[csv_data[0]] = mod_cdr_decode.decode_RSVPStat(val=csv_data[1])
            # Decode dateTimeConnect
            elif csv_data[0] == "dateTimeConnect":
              es_body[csv_data[0]] = mod_cdr_decode.decode_Time(val=csv_data[1])
            # Decode dateTimeDisconnect
            elif csv_data[0] == "dateTimeDisconnect":
              es_body[csv_data[0]] = mod_cdr_decode.decode_Time(val=csv_data[1])
            # Decode origDTMFMethod
            elif csv_data[0] == "origDTMFMethod":
              es_body[csv_data[0]] = mod_cdr_decode.decode_DTMFMethod(val=csv_data[1])
            # Decode destDTMFMethod
            elif csv_data[0] == "destDTMFMethod":
              es_body[csv_data[0]] = mod_cdr_decode.decode_DTMFMethod(val=csv_data[1])
            # Decode callSecuredStatus
            elif csv_data[0] == "callSecuredStatus":
              es_body[csv_data[0]] = mod_cdr_decode.decode_SecuredStatus(val=csv_data[1])
            # Link origLegCallIdentifier to callIdentifier
            elif csv_data[0] == "origLegCallIdentifier":
              es_body[csv_data[0]] = csv_data[1]
              es_body["callIdentifier"] = csv_data[1]
            # Decode duration
            elif csv_data[0] == "duration":
              es_body[csv_data[0]] = mod_cdr_decode.decode_duration(val=csv_data[1])
            # Save originalCalledPartyNumber for call sequence summary
            elif csv_data[0] == "originalCalledPartyNumber":
              origNum = csv_data[1]
              es_body[csv_data[0]] = csv_data[1]
            # Save finalCalledPartyNumber for call sequence summary
            elif csv_data[0] == "finalCalledPartyNumber":
              finNum = csv_data[1]
              es_body[csv_data[0]] = csv_data[1]
            # Write non-decoded values as is
            else:
              es_body[csv_data[0]] = csv_data[1]

          # Build call sequence summary if data is present
          if not origNum == "":
            if origNum == finNum:
              es_body["Call Sequence"] = "Call to: " + origNum
            else:
              es_body["Call Sequence"] = "Call to: " + origNum + " Forwarded to: " + finNum

          # Add filename for checking
          es_body["filename"] = file

          # Send CDR to ElasticSearch
          logger.debug(es.index(index=es_index,doc_type=es_type,body=es_body))

  time.sleep(.5)

def program_cleanup():
  print "program_cleanup - not implemented"

def reload_program_config():
  print "reload_program_config - not implemented"
<commit_msg>Delete mod_cdr_main2.py<commit_after><|endoftext|>


<commit_before>import os
import itertools
import locale

locale.setlocale(locale.LC_ALL, '')

def load_proc_to_names():
    general_translation = {}
    mount_translation = {}
    item_translation = {}
    troop_translation = {}
    legion_translation = {}

    glist = db().select(db.general.name, db.general.proc_name)
    mlist = db().select(db.mount.name, db.mount.proc_name)
    ilist = db().select(db.item.name, db.item.proc_name)
    tlist = db().select(db.troop.name, db.troop.proc_name)
    llist = db().select(db.legion.name, db.legion.proc_name)

    for row in glist:
        general_translation[row.proc_name] = row.name

    for row in mlist:
        mount_translation[row.proc_name] = row.name

    for row in ilist:
        item_translation[row.proc_name] = row.name

    for row in tlist:
        troop_translation[row.proc_name] = row.name

    for row in llist:
        legion_translation[row.proc_name] = row.name

    translation = [general_translation, mount_translation, item_translation, troop_translation, legion_translation]
    return translation

def parser(input):
    experience = {
        "user": "",
        "critical": 0,
        "regular": 0,
        "crit_damage": 0,
        "damage": 0,
        "health": 0,
        "gold": 0,
        "exp": 0,
    }

    obtained_items = {}
    proc_items = {}
    found_items = {}

    max_hit = []
    hit_list = {}

    proc_to_names = load_proc_to_names()

    log_file = []
    log_file = input.split('\n')

    for num, line in enumerate(list(log_file)):
        if "Found" in line:
            object = line.split('Found')[1][:-2]

            if not object in found_items:
                found_items[object] = 1
            else:
                found_items[object] += 1

        if "obtained" in line:
            object = line.split('obtained:')[1][:-2]

            if not object in obtained_items:
                obtained_items[object] = 1
            else:
                obtained_items[object] += 1

        if "contributed" in line:
            object, amount = line.split('contributed')
            object = object.strip()

            for proc_name in proc_to_names:
                if object in proc_name:
                    object = proc_name[str(object)]

            amount = int(amount.split()[0].replace(',', ''))

            if not object in proc_items:
                proc_items[object] = {'count': 1, 'damage': amount}
            else:
                proc_items[object]['count'] += 1
                proc_items[object]['damage'] = proc_items[object]['damage'] + amount

        if "experience!" in line:
            object = line.split()
            experience["user"] = object[0]

            # store damage dealt in hit_list history line #: damage
            damage = int(object[2].replace(',', ''))
            hit_list[num] = damage

            if "crit" in object[1]:
                experience["critical"] += 1
                experience["crit_damage"] = experience["crit_damage"] + damage
            else:
                experience["regular"] += 1
                experience["damage"] = experience["damage"] + damage

            for item in 5, 8, 11:
                amount = int(object[item].replace(',', ''))
                if item == 5:
                    experience["health"] = experience["health"] + amount
                elif item == 8:
                    experience["gold"] = experience["gold"] + amount
                else:
                    experience["exp"] = experience["exp"] + amount

        # if "restored" in line:
        #   # Like a Book has restored some of your Health.
        #   # Tollo Darkgaze has restored 4 Honor.

        # if "affected" in line:
        #   # Crystal Sight affected boss damage.
        #   # Bladezz' Blades affected boss damage.

        # if "says" in line:
        #   # Vigbjorn the Crazed says: "You believe me, Veritas, don't you? We'll hunt the blue yetis together!"

        # if "applied" in line:
        #   # *DEV* Mouse applied Magic: Begone, Fiends!
        #   # *DEV* ryanSMASH applied Magic: Hell's Knell

        # if "created" in line:
        #   # Master of Monsters has created a Steed of the Western Wold!
        #   # Master of Monsters has created a Blue Manticore!
        #   # Master of Monsters has created a Floating Eye!

    # find the biggest hit
    biggest_hit = max(hit_list, key=hit_list.get)

    # build out a history of biggest hit indexes
    experience_lines = []
    for a in sorted(hit_list.keys()):
        experience_lines.append(a)

    # find the previous hit before the biggest hit, or just map the current hit
    try:
        previous_hit = experience_lines[experience_lines.index(biggest_hit) - 1]
    except ValueError:
        previous_hit = biggest_hit

    # build out the last biggest hit history
    for hits in range(previous_hit + 1, biggest_hit + 1):
        max_hit.append(log_entries[hits])

    return experience, obtained_items, proc_items, found_items, log_file, max_hit, hit_list
<commit_msg>Langoliers refactor mode, naming the things<commit_after>import os
import itertools
import locale

locale.setlocale(locale.LC_ALL, '')

def load_proc_to_names():
    general_translation = {}
    mount_translation = {}
    item_translation = {}
    troop_translation = {}
    legion_translation = {}

    glist = db().select(db.general.name, db.general.proc_name)
    mlist = db().select(db.mount.name, db.mount.proc_name)
    ilist = db().select(db.item.name, db.item.proc_name)
    tlist = db().select(db.troop.name, db.troop.proc_name)
    llist = db().select(db.legion.name, db.legion.proc_name)

    for row in glist:
        general_translation[row.proc_name] = row.name

    for row in mlist:
        mount_translation[row.proc_name] = row.name

    for row in ilist:
        item_translation[row.proc_name] = row.name

    for row in tlist:
        troop_translation[row.proc_name] = row.name

    for row in llist:
        legion_translation[row.proc_name] = row.name

    translation = [general_translation, mount_translation, item_translation, troop_translation, legion_translation]
    return translation

def parser(input):
    experience = {
        "user": "",
        "critical": 0,
        "regular": 0,
        "crit_damage": 0,
        "damage": 0,
        "health": 0,
        "gold": 0,
        "exp": 0,
    }

    obtained_items = {}
    proc_items = {}
    found_items = {}

    max_hit = []
    hit_list = {}

    proc_to_names = load_proc_to_names()

    log_file = []
    log_file = input.split('\n')

    for num, line in enumerate(list(log_file)):
        if "Found" in line:
            object = line.split('Found')[1][:-2]

            if not object in found_items:
                found_items[object] = 1
            else:
                found_items[object] += 1

        if "obtained" in line:
            object = line.split('obtained:')[1][:-2]

            if not object in obtained_items:
                obtained_items[object] = 1
            else:
                obtained_items[object] += 1

        if "contributed" in line:
            object, amount = line.split('contributed')
            object = object.strip()

            for proc_name in proc_to_names:
                if object in proc_name:
                    object = proc_name[str(object)]

            amount = int(amount.split()[0].replace(',', ''))

            if not object in proc_items:
                proc_items[object] = {'count': 1, 'damage': amount}
            else:
                proc_items[object]['count'] += 1
                proc_items[object]['damage'] = proc_items[object]['damage'] + amount

        if "experience!" in line:
            object = line.split()
            experience["user"] = object[0]

            # store damage dealt in hit_list history line #: damage
            damage = int(object[2].replace(',', ''))
            hit_list[num] = damage

            if "crit" in object[1]:
                experience["critical"] += 1
                experience["crit_damage"] = experience["crit_damage"] + damage
            else:
                experience["regular"] += 1
                experience["damage"] = experience["damage"] + damage

            for item in 5, 8, 11:
                amount = int(object[item].replace(',', ''))
                if item == 5:
                    experience["health"] = experience["health"] + amount
                elif item == 8:
                    experience["gold"] = experience["gold"] + amount
                else:
                    experience["exp"] = experience["exp"] + amount

        # if "restored" in line:
        #   # Like a Book has restored some of your Health.
        #   # Tollo Darkgaze has restored 4 Honor.

        # if "affected" in line:
        #   # Crystal Sight affected boss damage.
        #   # Bladezz' Blades affected boss damage.

        # if "says" in line:
        #   # Vigbjorn the Crazed says: "You believe me, Veritas, don't you? We'll hunt the blue yetis together!"

        # if "applied" in line:
        #   # *DEV* Mouse applied Magic: Begone, Fiends!
        #   # *DEV* ryanSMASH applied Magic: Hell's Knell

        # if "created" in line:
        #   # Master of Monsters has created a Steed of the Western Wold!
        #   # Master of Monsters has created a Blue Manticore!
        #   # Master of Monsters has created a Floating Eye!

    # find the biggest hit
    biggest_hit = max(hit_list, key=hit_list.get)

    # build out a history of biggest hit indexes
    hit_indexes = []
    for a in sorted(hit_list.keys()):
        hit_indexes.append(a)

    # find the previous hit before the biggest hit, or just map the current hit
    try:
        previous_hit = hit_indexes[hit_indexes.index(biggest_hit) - 1]
    except ValueError:
        previous_hit = biggest_hit

    # build out the last biggest hit history
    for hits in range(previous_hit + 1, biggest_hit + 1):
        max_hit.append(log_file[hits])

    return experience, obtained_items, proc_items, found_items, log_file, max_hit, hit_list
<|endoftext|>