Source code for cytoflow.utility.custom_traits

#!/usr/bin/env python3.4
# coding: latin-1

# (c) Massachusetts Institute of Technology 2015-2018
# (c) Brian Teague 2018-2019
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

'''
cytoflow.utility.custom_traits
------------------------------

Custom traits for :class:`~cytoflow`
'''

from warnings import warn
import inspect

from traits.api import (BaseInt, BaseCInt, BaseFloat, BaseCFloat, BaseEnum, TraitType)
from . import scale
from . import CytoflowError, CytoflowWarning

import cytoflow


[docs]class PositiveInt(BaseInt): """ Defines a trait whose value must be a positive integer """ info_text = 'a positive integer'
[docs] def validate(self, obj, name, value): if self.allow_none and value == None: return None value = super().validate(obj, name, value) if (value > 0 or (self.allow_zero and value >= 0)): return value self.error(obj, name, value)
[docs]class PositiveCInt(BaseCInt): """ Defines a trait whose value must be a positive integer """ info_text = 'a positive integer'
[docs] def validate(self, obj, name, value): if self.allow_none and (value == "" or value == None): return None value = super().validate(obj, name, value) if (value > 0 or (self.allow_zero and value >= 0)): return value self.error(obj, name, value)
[docs]class PositiveFloat(BaseFloat): """ Defines a trait whose value must be a positive float """ info_text = 'a positive float'
[docs] def validate(self, obj, name, value): if self.allow_none and value == None: return None value = super().validate(obj, name, value) if (value > 0.0 or (self.allow_zero and value >= 0.0)): return value self.error(obj, name, value)
[docs]class PositiveCFloat(BaseCFloat): """ Defines a trait whose value must be a positive float """ info_text = 'a positive float'
[docs] def validate(self, obj, name, value): if self.allow_none and (value == "" or value == None): return None value = super().validate(obj, name, value) if (value > 0.0 or (self.allow_zero and value >= 0.0)): return value self.error(obj, name, value)
[docs]class FloatOrNone(BaseFloat): info_text = 'a float or None'
[docs] def validate(self, obj, name, value): if value == "" or value == None: return None else: return super().validate(obj, name, value)
[docs]class CFloatOrNone(BaseCFloat): info_text = 'a float or None'
[docs] def validate(self, obj, name, value): if value == None or value == "": return None else: return super().validate(obj, name, value)
[docs]class IntOrNone(BaseInt): info_text = 'an int or None'
[docs] def validate(self, obj, name, value): if value == None: return None else: return super().validate(obj, name, value)
[docs]class CIntOrNone(BaseCInt): info_text = 'an int or None'
[docs] def validate(self, obj, name, value): if value == None or value == "": return None else: return super().validate(obj, name, value)
[docs]class ScaleEnum(BaseEnum): """ Defines an enumeration that contains one of the registered data scales """ info_text = 'an enum containing one of the registered scales' def __init__ ( self, *args, **metadata ): """ Returns an Enum trait with values from the registered scales """ self.name = '' self.values = list(scale._scale_mapping.keys()) self.init_fast_validator( 5, self.values ) super(BaseEnum, self).__init__(scale._scale_default, **metadata )
[docs] def get_default_value(self): # this is so silly. get_default_value is ... called once? as traits # sets up? idunno. anyways, instead of returning _scale_default, we # need to return a reference to a function that returns _scale_Default. return (7, (self._get_default_value, (), None))
def _get_default_value(self): return scale._scale_default
[docs]class Removed(TraitType): """ Names a trait that was present in a previous version but was removed. Trait metadata: - **err_string** : the error string in the error - **gui** : if ``True``, don't return a backtrace (because it's very slow) - **warning** : if ``True``, raise a warning when the trait is referenced. Otherwise, raise an exception. """ def __init__(self, **metadata): metadata.setdefault('err_string', 'Trait {} has been removed') metadata.setdefault('transient', True) super().__init__(**metadata)
[docs] def get(self, obj, name): if not cytoflow.RUNNING_IN_GUI: # TODO - this is quite slow. come up with a better way. curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe) if calframe[1][3] == "copy_traits" or calframe[1][3] == "trait_get": return if self.warning: warn(self.err_string.format(name), CytoflowWarning) else: raise CytoflowError(self.err_string.format(name))
[docs] def set(self, obj, name, value): if not cytoflow.RUNNING_IN_GUI: curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe, 2) if calframe[1][3] == "copy_traits": return if self.warning: warn(self.err_string.format(name), CytoflowWarning) else: raise CytoflowError(self.err_string.format(name))
[docs]class Deprecated(TraitType): """ Names a trait that was present in a previous version but was renamed in this version. When the trait is accessed, a warning is raised, and the access is passed through to the new trait. Trait metadata: - **new** : the name of the new trait - **err_string** : the error string in the error - **gui** : if ``True``, don't return a backtrace (because it's very slow) """ def __init__(self, **metadata): metadata.setdefault('err_string', 'Trait {} is deprecated; please use {}') metadata.setdefault('transient', True) super().__init__(**metadata)
[docs] def get(self, obj, name): if not cytoflow.RUNNING_IN_GUI: curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe) if calframe[1][3] != "copy_traits" and calframe[1][3] != 'trait_get': warn(self.err_string.format(name, self.new), CytoflowWarning) return getattr(obj, self.new)
[docs] def set(self, obj, name, value): if not cytoflow.RUNNING_IN_GUI: curframe = inspect.currentframe() calframe = inspect.getouterframes(curframe) if calframe[1][3] != "copy_traits": warn(self.err_string.format(name, self.new), CytoflowWarning) setattr(obj, self.new, value)