class TestModel(BaseModel): a_key = properties.String('A key') sub_instance = properties.Instance( 'Sub Instance', instance_class=BaseModel, ) list = properties.List( 'List', prop=properties.Instance('List Instance', instance_class=BaseModel), ) list_string = properties.List( 'List of Strings', prop=properties.String('String'), ) not_a_field = True
class RasterMetaData(properties.HasProperties): """An object to contain all the information for a single swath. """ #https://landsat.usgs.gov/how-do-landsat-8-band-combinations-differ-landsat-7-or-landsat-5-satellite-data # Metadata data_provider = properties.String('The data provider') satellite = properties.String('The satellite from which data was aquired') instrument = properties.String('The instrument on the satellite') acquisition_date = properties.String('The date of acquisition', required=False) scene_center_time = properties.String('Center time', required=False) level1_production_date = properties.String('Production date', required=False) solar_angles = properties.Instance('The solar angles', SolarAngle, required=False) earth_sun_distance = properties.Float('The earth-sun distance', required=False) product_id = properties.String('Data product ID', required=False) lpgs_metadata_file = properties.String('metadata file', required=False) wrs = properties.Instance('WRS', WRS, required=False) # TODO modis = properties.Instance('Modis', Modis, required=False) corner = properties.List('The corner points', prop=Corner) # Spatial Reference bounding_coordinates = properties.Instance('The bounding coordinates', BoundingCoordinates) projection_information = properties.Instance('The projection', Projection) orientation_angle = properties.Float('The orientation angle', min=-360.0, max=360.0)
class ManyProperties(properties.HasProperties): mystr = properties.String( 'my string', required=False, ) myarr = properties.Array( 'my array', required=False, ) myinst = properties.Instance( 'my HP1', instance_class=HP1, required=False, ) mylist = properties.List( 'my list of HP1', prop=HP1, required=False, default=properties.utils.undefined ) myunion = properties.Union( 'string or HP1', props=(HP1, properties.String('')), required=False, )
class SurfaceElement(ProjectElement): """Contains mesh, data, textures, and options of a surface""" geometry = properties.Union('Structure of the surface element', props=(SurfaceGeometry, SurfaceGridGeometry)) textures = properties.List( 'Images mapped on the surface element', prop=ImageTexture, required=False, default=list, ) subtype = properties.StringChoice('Category of Surface', choices=('surface', ), default='surface') def toVTK(self): """Convert the surface to a its appropriate VTK data object type.""" from vtk.util import numpy_support as nps output = self.geometry.toVTK() # TODO: handle textures # Now add point data: for data in self.data: arr = data.array.array c = nps.numpy_to_vtk(num_array=arr) c.SetName(data.name) output.GetPointData().AddArray(c) return output
class Person(BaseModel): """This is a subset of the data representing a Customer, User or Team. The ``type`` property will specify if this person is represented by a ``user``, ``customer`` or ``team``. """ def __init__(self, **kwargs): value = kwargs.pop('customer_person_type', False) self.type = 'customer' if value else 'user' return super(Person, self).__init__(**kwargs) full_name = properties.String( 'Full name for the customer', ) first_name = properties.String( 'First name', required=True, ) last_name = properties.String( 'Last name', required=True, ) email = properties.String( 'Email', ) emails = properties.List( 'Email addresses for this person.', prop=properties.String( 'Email Address', ), ) phone = properties.String( 'Phone is only populated when the Person is a customer associated ' 'with a Conversation of type ``phone`` and a phone number was ' 'specified at the time the conversation was created.', ) type = properties.StringChoice( 'The type of person.', choices=['user', 'customer', 'team'], default='customer', required=True, ) photo_url = properties.String( 'The user\'s photo, if one exists.', ) created_at = properties.DateTime( 'UTC time when this customer was created.', ) modified_at = properties.DateTime( 'UTC time when this customer was modified.', ) @properties.Bool('customer boolean') def customer_person_type(self): return self.type == 'customer' @customer_person_type.setter def customer_person_type(self, value): self.type = 'customer' if value else 'user'
class _BaseElementSurface(_BaseElement): """Base class for surface elements""" data = properties.List( 'Data defined on the element', prop=properties.Union( '', props=[ Pointer('', DataBasic), Pointer('', DataCategory), Pointer('', TextureProjection), ], ), max_length=100, default=list, ) defaults = InstanceSnapshot( 'Default visualization options', OptionsSurface, default={ 'visible': True, 'color': { 'value': 'random' }, 'opacity': { 'value': 1. }, 'wireframe': { 'active': False }, 'textures': [], }, )
def test_list_default(self): class ListDefault(properties.List): _class_default = list class HasIntList(properties.HasProperties): intlist = ListDefault('list of ints', properties.Integer('')) hil = HasIntList() assert isinstance(hil.intlist, list) assert len(hil.intlist) == 0 assert hil.intlist is not HasIntList().intlist with warnings.catch_warnings(record=True) as w: properties.List('list', properties.Integer('', default=5)) assert len(w) == 1 assert issubclass(w[0].category, RuntimeWarning) class HasDefaultIntList(properties.HasProperties): intlist = properties.List('list of ints', properties.Integer('', default=5)) hdil = HasDefaultIntList() assert hdil.intlist is None
class _BaseElementPointSet(_BaseElement): """Base class for point-set elements""" data = properties.List( 'Data defined on the element', prop=properties.Union( '', props=[ Pointer('', DataBasic), Pointer('', DataCategory), Pointer('', TextureProjection), ], ), max_length=100, default=list, ) defaults = InstanceSnapshot( 'Default visualization options', OptionsPoints, default={ 'visible': True, 'color': { 'value': 'random' }, 'opacity': { 'value': 1. }, }, )
class Slide(_BaseCollaborationModel, spatial.base._BaseResource): """Slides provide a snapshot of a 3D scene They also provide a canvas for annotating the scene. By creating several slides, you can tell a story around your 3D data. """ BASE_TYPE = 'slides' scene = spatial.base.InstanceSnapshot( 'Current state of the 3D scene', instance_class=Scene, ) annotation_plane = spatial.base.InstanceSnapshot( 'Drawing plane for annotations perpendicular to line of sight', instance_class=DrawingPlane, ) annotations = properties.List( 'List of annotations on the scene', properties.Union( '', props=[ spatial.base.InstanceSnapshot('', AnnotationText), spatial.base.InstanceSnapshot('', AnnotationInk), ], ), max_length=30, default=list, )
class CustomField(BaseModel): """This represents optional data that can defined for specific mailbox and filled when creating or updating a Conversation.""" field_name = properties.String( 'The name of the field; note that this may change if a field ' 'is renamed, but the ``id`` will not.', required=True, ) field_type = properties.StringChoice( 'Type of the field.', choices=[ 'SINGLE_LINE', 'MULTI_LINE', 'DATA', 'NUMBER', 'DROPDOWN', ], default='SINGLE_LINE', required=True, ) required = properties.Bool('Flag for UI to mark the field as required.', ) order = properties.Integer( 'Relative order of the custom field. Can be ``null`` or a number ' 'between ``0`` and ``255``.', min=0, max=255, ) options = properties.List( 'Field options', prop=Option, )
class ScalarColormap(ContentModel): """Length-128 color gradient with min/max values, used with ScalarData""" gradient = properties.Instance( 'length-128 ColorArray defining the gradient', ColorArray ) limits = properties.List( 'Data range associated with the gradient', prop=properties.Float(''), min_length=2, max_length=2, default=properties.undefined, ) @properties.validator('gradient') def _check_gradient_length(self, change): #pylint: disable=no-self-use """Ensure gradient is length-128""" if len(change['value']) != 128: raise ValueError('Colormap gradient must be length 128') @properties.validator('limits') def _check_limits_on_change(self, change): #pylint: disable=no-self-use """Ensure limits are valid""" if change['value'][0] > change['value'][1]: raise ValueError('Colormap limits[0] must be <= limits[1]') @properties.validator def _check_limits_on_validate(self): """Ensure limits are valid""" self._check_limits_on_change({'value': self.limits})
class SearchCustomer(Person): """This represents a customer as returned by a search.""" photo_type = properties.StringChoice( 'Type of photo.', choices=[ 'unknown', 'gravatar', 'twitter', 'facebook', 'googleprofile', 'googleplus', 'linkedin', ], ) gender = properties.StringChoice( 'Gender of this customer.', choices=['female', 'male', 'unknown'], default='unknown', required=True, ) age = properties.String('Age (or age range) of this customer.', ) organization = properties.String( 'Company/Organization the customer identifies with.', ) job_title = properties.String('Job title at company/organization.', ) location = properties.String('Location', ) emails = properties.List( 'Email addresses for the customer.', prop=properties.String(''), )
class SurveyVRM(BaseSurvey): """""" source_list = properties.List( "A list of sources for the survey", properties.Instance("A SimPEG source", BaseSrcVRM), default=[], ) t_active = properties.Array( "Boolean array where True denotes active data in the inversion", dtype=bool) def __init__(self, source_list=None, **kwargs): t_active = kwargs.pop("t_active", None) super(SurveyVRM, self).__init__(source_list=source_list, **kwargs) self._nD_all = self.vnD.sum() self._nD = self._nD_all if t_active is None: self.t_active = np.ones(self._nD_all, dtype=bool) else: self.t_active = t_active @properties.validator("t_active") def _t_active_validator(self, change): if self._nD_all != len(change["value"]): raise ValueError( "Length of t_active boolean array must equal number of data. Number of data is %i" % self._nD_all) @property def nD(self): if self._nD is None: self._nD = np.sum(self.t_active) return self._nD def set_active_interval(self, tmin, tmax): """Set active times using an interval""" srcList = self.source_list nSrc = len(srcList) tActBool = np.array([]) for pp in range(0, nSrc): rxList = srcList[pp].receiver_list nRx = len(rxList) for qq in range(0, nRx): times = rxList[qq].times nLoc = np.shape(rxList[qq].locations)[0] tActBool = np.r_[tActBool, np.kron(np.ones(nLoc), times)] self.t_active = (tActBool >= tmin) & (tActBool <= tmax) self._nD = np.sum(self.t_active)
class ProjectElement(ContentModel): """Base ProjectElement class for OMF file ProjectElement subclasses must define their mesh. ProjectElements include PointSet, LineSet, Surface, and Volume """ data = properties.List( 'Data defined on the element', prop=ProjectElementData, required=False, default=list, ) color = properties.Color('Solid color', default='random') geometry = None @properties.validator def _validate_data(self): """Check if element is built correctly""" assert self.geometry is not None, 'ProjectElement must have a mesh' for i, dat in enumerate(self.data): if dat.location not in self.geometry._valid_locations: #pylint: disable=protected-access raise ValueError( 'Invalid location {loc} - valid values: {locs}'.format( loc=dat.location, locs=', '.join(self.geometry._valid_locations) #pylint: disable=protected-access )) valid_length = self.geometry.location_length(dat.location) if len(dat.array) != valid_length: raise ValueError( 'data[{index}] length {datalen} does not match ' '{loc} length {meshlen}'.format(index=i, datalen=len(dat.array), loc=dat.location, meshlen=valid_length)) return True
class Address(BaseModel): """This represents an address.""" lines = properties.List( 'Address line strings', prop=properties.String('Address line string', ), ) city = properties.String( 'City', required=True, ) state = properties.String( 'State', required=True, ) postal_code = properties.String( 'Postal Code', required=True, ) country = properties.String( 'Country', required=True, ) created_at = properties.DateTime( 'UTC time when this address was created.', ) modified_at = properties.DateTime( 'UTC time when this address was modified.', )
class CameraStandard(_BaseCamera): """Base class for Standard Cameras Both orthographic and perspective cameras are built on this """ mode = properties.StringChoice( 'View mode of camera', choices=['perspective', 'orthographic'], default='orthographic', ) target = properties.Vector3( 'Center of rotation of camera relative to the scene origin', default=lambda: [0., 0., 0.], ) radius = properties.Float( 'Distance of camera to target', default=5., ) zoom = properties.Float( 'Zoom level of camera', default=1., ) rotation = properties.List( 'Quaternion rotation of the camera relative to the scene', properties.Float(''), min_length=4, max_length=4, default=lambda: [0., 0., 0., 1.], ) up_direction = properties.Vector3( 'Up direction of camera', default='up', )
class ManyProperties(properties.HasProperties): mystr = properties.String( 'my string', serializer=reverse, deserializer=reverse, ) myarr = properties.Array( 'my array', serializer=to_string, deserializer=from_string, ) myinst = properties.Instance( 'my HP1', instance_class=HP1, serializer=serialize_a_only, deserializer=deserialize_from_a, ) mylist = properties.List( 'my list of HP1', prop=HP1, serializer=sum_of_a, deserializer=from_sum, ) myunion = properties.Union( 'string or HP1', props=(HP1, properties.String('')), serializer=just_the_classname, deserializer=reverse, )
class ColorArray(ScalarArray): """Shared array of Colors""" array = properties.List( 'Shared array of Colors', prop=properties.Color(''), default=list, )
class DateTimeArray(ScalarArray): """Shared array of DateTimes""" array = properties.List( 'Shared array of DateTimes', prop=properties.DateTime(''), default=list, )
class StringArray(ScalarArray): """Shared array of text strings""" array = properties.List( 'Shared array of text strings', prop=properties.String(''), default=list, )
class Simple(properties.HasProperties): a = properties.List( doc='2 ints', prop=properties.Integer(''), min_length=2, max_length=2, )
class HasLists(properties.HasProperties): basic = properties.List('', properties.Integer('')) advanced = properties.List('', properties.Integer(''), observe_mutations=True) def __init__(self, **kwargs): self._basic_tic = 0 self._advanced_tic = 0 @properties.validator('basic') def _basic_val(self, change): self._basic_tic += 1 @properties.validator('advanced') def _advanced_val(self, change): self._advanced_tic += 1
class Volume(CompositeResource): """Contains all the information about a 3D volume""" mesh = properties.Instance( doc='Mesh', instance_class=Mesh3DGrid, default=Mesh3DGrid, ) data = properties.List( doc='Data', prop=_VolumeBinder, coerce=True, required=False, default=list, ) opts = properties.Instance( doc='Options', instance_class=_VolumeOptions, default=_VolumeOptions, ) def _nbytes(self): return self.mesh._nbytes() + sum(d.data._nbytes() for d in self.data) @properties.validator def _validate_data(self): """Check if resource is built correctly""" for ii, dat in enumerate(self.data): assert dat.location == 'CC' # in ('N', 'CC') valid_length = (self.mesh.nC if dat.location == 'CC' else self.mesh.nN) if len(dat.data.array) != valid_length: raise ValueError( 'volume.data[{index}] length {datalen} does not match ' '{loc} length {meshlen}'.format(index=ii, datalen=len( dat.data.array), loc=dat.location, meshlen=valid_length)) return True def _to_omf(self): import omf element = omf.VolumeElement( name=self.title or '', description=self.description or '', geometry=self.mesh._to_omf(), color=self.opts.color or 'random', data=[], ) for data in self.data: if data.location == 'CC': location = 'cells' else: location = 'vertices' omf_data = data.data._to_omf() omf_data.location = location element.data.append(omf_data) return element
class HasIntAndList(properties.HasProperties): myints = properties.Union('union of int or int list', props=[ properties.Integer(''), properties.List( '', properties.Integer(''), min_length=2) ])
class DateTimeColormap(ScalarColormap): """Length-128 color gradient with min/max values, used with DateTimeData""" limits = properties.List( 'Data range associated with the gradient', prop=properties.DateTime(''), min_length=2, max_length=2, default=properties.undefined, )
class Ruler(_BaseSceneComponent): """Ruler class Contains the path of the ruler as well as info about the objects it is measuring to and from """ positions = properties.List( 'Endpoints of the ruler', properties.Vector3(''), min_length=2, max_length=2, ) objects = properties.List( 'URL pointers of objects we are measuring from/to', Pointer('', spatial.elements._BaseElement), min_length=2, max_length=2, )
class _BaseAnnotation(_BaseSlideComponent): """Base class for all annotations""" uid = properties.String('Locally unique ID from client', required=False) position = properties.List( 'Location of annotation on slide plane', properties.Float(''), min_length=2, max_length=2, ) color = properties.Color('Annotation color')
class Projection(properties.HasProperties): projection = properties.String('The coordinate projection') datum = properties.String('The projection datum') units = properties.String('The projection units') corner_point = properties.List('The corner points', prop=CornerPoint) grid_origin = properties.String('The grid origin') utm_proj_params = properties.Dictionary('The UTM projection parameters', required=False) ps_proj_params = properties.Dictionary('The PS projection parameters', required=False) albers_proj_params = properties.Dictionary('The Albers projection parameters', required=False) sin_proj_params = properties.Dictionary('The Sin projection parameters', required=False)
class PointSetElement(ProjectElement): """Contains mesh, data, textures, and options of a point set""" geometry = properties.Instance('Structure of the point set element', instance_class=PointSetGeometry) textures = properties.List( 'Images mapped on the element', prop=ImageTexture, required=False, default=list, ) subtype = properties.StringChoice('Category of PointSet', choices=('point', 'collar', 'blasthole'), default='point') def toVTK(self): """Convert the point set to a ``vtkPloyData`` data object which contatins the point set.""" import vtk import numpy as np from vtk.util import numpy_support as nps points = self.geometry.vertices npoints = self.geometry.num_nodes # Make VTK cells array cells = np.hstack((np.ones( (npoints, 1)), np.arange(npoints).reshape(-1, 1))) cells = np.ascontiguousarray(cells, dtype=np.int64) vtkcells = vtk.vtkCellArray() vtkcells.SetCells(npoints, nps.numpy_to_vtkIdTypeArray(cells, deep=True)) # Convert points to vtk object pts = vtk.vtkPoints() pts.SetNumberOfPoints(self.geometry.num_nodes) pts.SetData(nps.numpy_to_vtk(points)) # Create polydata output = vtk.vtkPolyData() output.SetPoints(pts) output.SetVerts(vtkcells) # TODO: handle textures # Now add point data: for data in self.data: arr = data.array.array c = nps.numpy_to_vtk(num_array=arr) c.SetName(data.name) output.GetPointData().AddArray(c) return output
class MappedData(ProjectElementData): """Data array of indices linked to legend values or -1 for no data""" array = properties.Instance( 'indices into 1 or more legends for locations on a mesh', ScalarArray ) legends = properties.List( 'legends into which the indices map', Legend, default=list, ) @property def indices(self): """Allows getting/setting array with more intuitive term indices""" return self.array @indices.setter def indices(self, value): self.array = value def value_dict(self, i): """Return a dictionary of legend entries based on index""" entry = {legend.name: legend.values[self.indices[i]] #pylint: disable=unsubscriptable-object for legend in self.legends} #pylint: disable=not-an-iterable return entry @properties.validator('array') def _validate_min_ind(self, change): #pylint: disable=no-self-use """This validation call fires immediately when indices is set""" if change['value'].array.dtype.kind != 'i': raise ValueError('DataMap indices must be integers') if np.min(change['value'].array) < -1: raise ValueError('DataMap indices must be >= -1') @properties.validator def _validate_indices(self): """This validation call fires on validate() after everything is set""" if np.min(self.indices.array) < -1: #pylint: disable=no-member raise ValueError( 'Indices of DataMap {} must be >= -1'.format(self.name) ) for legend in self.legends: #pylint: disable=not-an-iterable if np.max(self.indices.array) >= len(legend.values): #pylint: disable=no-member raise ValueError( 'Indices of DataMap {dm} exceed number of available ' 'entries in Legend {leg}'.format( dm=self.name, leg=legend.name ) ) return True