Source code for binoculars.backend

from . import util, errors, dispatcher


[docs]class ProjectionBase(util.ConfigurableObject):
[docs] def parse_config(self, config): super(ProjectionBase, self).parse_config(config) res = config.pop("resolution") # or just give 1 number for # all dimensions Optional, set the limits of the space object # in projected coordinates. Syntax is same as numpy # e.g. 'limits = [:0,-1:,:], [0:,:-1,:], [:0,:-1,:], # [0:,-1:,:]' self.config.limits = util.parse_pairs(config.pop("limits", None)) labels = self.get_axis_labels() if self.config.limits is not None: for lim in self.config.limits: if len(lim) != len(labels): raise errors.ConfigError( "dimension mismatch between projection axes ({0}) and limits specification ({1}) in {2}".format( # noqa labels, self.config.limits, self.__class__.__name__ ) ) # noqa if "," in res: self.config.resolution = util.parse_tuple(res, type=float) if not len(labels) == len(self.config.resolution): raise errors.ConfigError( "dimension mismatch between projection axes ({0}) and resolution specification ({1}) in {2}".format( # noqa labels, self.config.resolution, self.__class__.__name__ ) ) # noqa else: self.config.resolution = tuple([float(res)] * len(labels))
[docs] def project(self, *args): raise NotImplementedError
[docs] def get_axis_labels(self): raise NotImplementedError
[docs]class Job(object): weight = 1.0 # estimate of job difficulty (arbitrary units) def __init__(self, **kwargs): self.__dict__.update(kwargs)
[docs]class InputBase(util.ConfigurableObject): """Generate and process Job()s. Note: there is no guarantee that generate_jobs() and process_jobs() will be called on the same instance, not even in the same process or on the same computer!"""
[docs] def parse_config(self, config): super(InputBase, self).parse_config(config) # approximate number of images per job, only useful when # running on the oar cluster self.config.target_weight = int(config.pop("target_weight", 1000))
[docs] def generate_jobs(self, command): """Receives command from user, yields Job() instances""" raise NotImplementedError
[docs] def process_job(self, job): """Receives a Job() instance, yields (intensity, args_to_be_sent_to_a_Projection_instance) Job()s could have been pickle'd and distributed over a cluster """ self.metadata = util.MetaBase("job", job.__dict__)
[docs] def get_destination_options(self, command): """Receives the same command as generate_jobs(), but returns dictionary that will be used to .format() the dispatcher:destination configuration value.""" return {}
[docs]def get_dispatcher(config, main, default=None): return _get_backend( config, "dispatcher", dispatcher.DispatcherBase, default=default, args=[main] )
[docs]def get_input(config, default=None): return _get_backend(config, "input", InputBase, default=default)
[docs]def get_projection(config, default=None): return _get_backend(config, "projection", ProjectionBase, default=default)
def _get_backend(config, section, basecls, default=None, args=[], kwargs={}): if isinstance(config, util.ConfigSection): return config.class_(config, *args, **kwargs) type = config.pop("type", default) if type is None: raise errors.ConfigError( "required option 'type' not given in section '{0}'".format(section) # noqa ) type = type.strip() if ":" in type: try: modname, clsname = type.split(":") except ValueError: raise errors.ConfigError( "invalid type '{0}' in section '{1}'".format(type, section) ) try: backend = __import__( "backends.{0}".format(modname), globals(), locals(), [], 1 ) except ImportError as e: raise errors.ConfigError( "unable to import module backends.{0}: {1}".format(modname, e) # noqa ) module = getattr(backend, modname) elif section == "dispatcher": module = dispatcher clsname = type else: raise errors.ConfigError( "invalid type '{0}' in section '{1}'".format(type, section) ) clsname = clsname.lower() names = dict((name.lower(), name) for name in dir(module)) if clsname in names: cls = getattr(module, names[clsname]) if issubclass(cls, basecls): return cls(config, *args, **kwargs) else: raise errors.ConfigError( "type '{0}' not compatible in section '{1}': expected class derived from '{2}', got '{3}'".format( # noqa type, section, basecls.__name__, cls.__name__ ) ) # noqa else: raise errors.ConfigError( "invalid type '{0}' in section '{1}'".format(type, section) ) # noqa