Ejemplo n.º 1
0
        class HasSets(properties.HasProperties):
            basic = properties.Set('', properties.Integer(''))
            advanced = properties.Set('',
                                      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
Ejemplo n.º 2
0
    def test_with_None_and_no_default(self):
        
        target = properties.Integer()

        with self.assertRaises(properties.ValidationError) as e:
            value = target('Test', None)

        self.assertIn('Test', e.exception.message)
Ejemplo n.º 3
0
        class HasNestedList(properties.HasProperties):

            nested_list = properties.List(
                'This is not a great idea...',
                properties.List('',
                                properties.Integer(''),
                                observe_mutations=True),
                observe_mutations=om,
            )
Ejemplo n.º 4
0
class GridInfo(properties.HasProperties):
    """Internal helper class to store Surfer grid properties and create
    ``vtkImageData`` objects from them.
    """

    ny = properties.Integer('number of columns', min=2)
    nx = properties.Integer('number of rows', min=2)
    xll = properties.Float('x-value of lower-left corner')
    yll = properties.Float('y-value of lower-left corner')
    dx = properties.Float('x-axis spacing')
    dy = properties.Float('y-axis spacing')
    dmin = properties.Float('minimum data value', required=False)
    dmax = properties.Float('maximum data value', required=False)
    data = properties.Array('grid of data values', shape=('*', ))

    def mask(self):
        """Mask the no data value"""
        data = self.data
        nans = data >= 1.701410009187828e38
        if np.any(nans):
            data = np.ma.masked_where(nans, data)
        err_msg = "{} of data ({}) doesn't match that set by file ({})."
        if not np.allclose(self.dmin, np.nanmin(data)):
            raise _helpers.PVGeoError(
                err_msg.format('Min', np.nanmin(data), self.dmin))
        if not np.allclose(self.dmax, np.nanmax(data)):
            raise _helpers.PVGeoError(
                err_msg.format('Max', np.nanmax(data), self.dmax))
        self.data = data
        return

    def to_vtk(self, output=None, z=0.0, dz=1.0, data_name='Data'):
        """Convert to a ``vtkImageData`` object"""
        self.mask()
        self.validate()
        if output is None:
            output = vtk.vtkImageData()
        # Build the data object
        output.SetOrigin(self.xll, self.yll, z)
        output.SetSpacing(self.dx, self.dy, dz)
        output.SetDimensions(self.nx, self.ny, 1)
        vtkarr = interface.convert_array(self.data, name=data_name)
        output.GetPointData().AddArray(vtkarr)
        return output
Ejemplo n.º 5
0
class Plot(_BaseSceneComponent):
    """Object describing the contents of the 3D scene

    Contains info about how a plot is positioned in the scene, as well
    as the plot limits. Also contains active elements, slices, and
    measurements in the plot.
    """
    position = properties.Vector3(
        'x,y,z position of the plot center relative to scene origin',
        default=lambda: [0., 0, 0],
    )
    scale = properties.Vector3(
        'x,y,z scale of the plot coordinate system relative to scene '
        'coordinate system',
        default=lambda: [1., 1, 1],
    )
    rotation = properties.List(
        'Quaternion rotation of plot axes relative to scene axes',
        properties.Float(''),
        min_length=4,
        max_length=4,
        default=lambda: [0., 0, 0, 1],
    )
    lims = properties.List(
        'x,y,z limits, defined in plot coordinates',
        properties.Vector2(''),
        min_length=3,
        max_length=3,
        default=lambda: [[0, 0.00001]] * 3,
    )
    exaggeration = properties.List(
        'x,y,z exaggeration of the plot coordinates',
        properties.Integer('', min=1),
        default=lambda: [1, 1, 1],
    )
    slice_groups = properties.List(
        'Active slice groups; currently only one is supported',
        SliceGroup,
        max_length=1,
        default=lambda: [SliceGroup()],
    )
    measurements = properties.List(
        'List of active ruler instances; currently only one is supported',
        Ruler,
        max_length=1,
        default=list,
    )
    views = properties.List(
        'List of element views in the plot',
        properties.Union('', [
            view for key, view in _BaseSceneComponent._REGISTRY.items()
            if key[0] != '_' and issubclass(view, _BaseElementView)
        ]),
        max_length=100,
        default=list,
    )
Ejemplo n.º 6
0
class GridSpec(properties.HasProperties):
    """A ``GridSpec`` object provides the details of a single axis along a grid.
    If you have a 3D grid then you will have 3 ``GridSpec`` objects.
    """
    n = properties.Integer('The number of components along this dimension.')
    min = properties.Integer(
        'The minimum value along this dimension. The origin.', default=0)
    sz = properties.Integer('The uniform cell size along this dimension.',
                            default=1)
    nnodes = properties.Integer(
        'The number of grid nodes to consider on either \
        side of the origin in the output map',
        required=False)

    @properties.validator
    def _validate_nnodes(self):
        if self.nnodes is None:
            self.nnodes = self.n // 2
        return True
Ejemplo n.º 7
0
        class ErrorListeners(properties.HasProperties):
            a = properties.Integer('int a')

            @properties.observer('a')
            def _obs(self, change):
                raise ObserveError()

            @properties.validator('a')
            def _val(self, change):
                raise ValidateError()
Ejemplo n.º 8
0
class ExponentialSinusoidSimulation(LinearSimulation):
    """
    This is the simulation class for the linear problem consisting of
    exponentially decaying sinusoids. The rows of the G matrix are

    .. math::

        \\int_x e^{p j_k x} \\cos(\\pi q j_k x) \\quad, j_k \\in [j_0, ..., j_n]
    """

    n_kernels = properties.Integer(
        "number of kernels defining the linear problem", default=20
    )

    p = properties.Float("rate of exponential decay of the kernel", default=-0.25)

    q = properties.Float("rate of oscillation of the kernel", default=0.25)

    j0 = properties.Float("maximum value for :math:`j_k = j_0`", default=0.0)

    jn = properties.Float("maximum value for :math:`j_k = j_n`", default=60.0)

    def __init__(self, **kwargs):
        super(ExponentialSinusoidSimulation, self).__init__(**kwargs)

    @property
    def jk(self):
        """
        Parameters controlling the spread of kernel functions
        """
        if getattr(self, "_jk", None) is None:
            self._jk = np.linspace(self.j0, self.jn, self.n_kernels)
        return self._jk

    def g(self, k):
        """
        Kernel functions for the decaying oscillating exponential functions.
        """
        return np.exp(self.p * self.jk[k] * self.mesh.vectorCCx) * np.cos(
            np.pi * self.q * self.jk[k] * self.mesh.vectorCCx
        )

    @property
    def G(self):
        """
        Matrix whose rows are the kernel functions
        """
        if getattr(self, "_G", None) is None:
            G = np.empty((self.n_kernels, self.mesh.nC))

            for i in range(self.n_kernels):
                G[i, :] = self.g(i) * self.mesh.hx

            self._G = G
        return self._G
Ejemplo n.º 9
0
class DomainConditionInteger(DomainCondition):
    """This represents an integer query."""

    value = properties.Integer(
        'Integer Value',
        required=True,
    )

    def __str__(self):
        """Return a string usable as a query part in an API request."""
        return '%s:%d' % (self.field_name, self.value)
class DispositionTypeParams(BaseModel):

    allowChangeTimer = properties.Bool(
        'Whether the agent can change the redial timer for this disposition.',
    )
    attempts = properties.Integer('Number of redial attempts.', )
    timer = properties.Instance(
        'Redial timer.',
        instance_class=Timer,
    )
    useTimer = properties.Bool(
        'Whether this disposition uses a redial timer.', )
Ejemplo n.º 11
0
class Option(BaseModel):
    """This represents option for a custom field of type ``DROPDOWN``."""

    label = properties.String(
        'Label of the option.',
        required=True,
    )
    order = properties.Integer(
        'Relative order of the custom field. Can be ``null`` or a number '
        'between ``0`` and ``255``.',
        min=0,
        max=255,
    )
class GeneralOverview(BaseModel):
    """Object that holds a general overview of other objects.

    This is the object that is typically returned by the API, which holds the
    high level information & how to access the actual dataset.
    """

    count = properties.Integer(
        'Total amount of reviews for this record.',
    )
    link = properties.String(
        'Link to the detailed review information in the Cannabis Reports '
        'API.',
    )
Ejemplo n.º 13
0
class SquareLoop(Point):
    """Square loop receiver

    Measurements with this type of receiver are the field, integrated over the
    area of the loop, then multiplied by the number of coils, then normalized
    by the dipole moment. As a result, the units for fields predicted with this
    type of receiver are the same as 'h', 'b', 'dhdt' and 'dbdt', respectively.

    """

    width = properties.Float("Square loop width", min=1e-6)
    nTurns = properties.Integer("Number of loop turns", min=1, default=1)
    quadOrder = properties.Integer(
        "Order for numerical quadrature integration over loop", min=1, max=7, default=3
    )

    def __init__(self, locations, **kwargs):

        if locations.shape[1] != 3:
            raise ValueError(
                "Rx locations (xi,yi,zi) must be np.array(N,3) where N is the number of stations"
            )

        super(SquareLoop, self).__init__(locations, **kwargs)
Ejemplo n.º 14
0
    def test_list_default(self):
        class HasIntList(properties.HasProperties):
            intlist = properties.List('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)
Ejemplo n.º 15
0
class _BaseFile(_BaseUIDModel):
    """Base class for File resources

    The properties defined here apply to any generic file. Note that
    this file resource does not actually store the binary file itself,
    only its metadata.
    """

    BASE_TYPE = 'files'

    _REGISTRY = OrderedDict()

    content_type = properties.String('Content type of the file')
    content_length = properties.Integer(
        'Content length of the file',
        min=0,
    )
Ejemplo n.º 16
0
class SearchConversation(BaseConversation):
    """This represents a conversation as returned by search results."""

    mailbox_id = properties.Integer(
        'The ID of the mailbox this conversation is in.',
        required=True,
    )
    customer_name = properties.String(
        'Name of the customer this conversation is regarding.',
        required=True,
    )
    customer_email = properties.String(
        'Email address of the customer',
        required=True,
    )
    has_attachments = properties.Bool(
        '``True`` when the conversation has at least one attachment.', )
Ejemplo n.º 17
0
        class HasDynamicProperty(properties.HasProperties):
            my_int = properties.Integer('an int')

            @properties.Integer('a dynamic int')
            def my_doubled_int(self):
                if self.my_int is None:
                    raise ValueError('my_doubled_int depends on my_int')
                return self.my_int * 2

            @properties.Vector3('a vector')
            def my_vector(self):
                self.validate()
                if self.my_int is None:
                    raise ValueError('my_vector depends on my_int')
                val = [
                    float(val)
                    for val in [self.my_int, self.my_int, self.my_doubled_int]
                ]
                return val
Ejemplo n.º 18
0
class Tag(BaseModel):

    tag = properties.String(
        'The tag value.',
        required=True,
    )
    slug = properties.String(
        'Slugified version of the tag value.',
    )
    count = properties.Integer(
        'The number of times the tag is used.',
    )
    color = properties.Color(
        'The tag color.',
    )
    created_at = properties.DateTime(
        'UTC time when this tag was created.',
    )
    modified_at = properties.DateTime(
        'UTC time when this tag was modified.',
    )
Ejemplo n.º 19
0
class IO(properties.HasProperties):
    """"""

    # Survey
    survey_layout = properties.StringChoice(
        "Survey geometry of DC surveys",
        default="SURFACE",
        choices=["SURFACE", "BOREHOLE", "GENERAL"],
    )

    survey_type = properties.StringChoice(
        "DC-IP Survey type",
        default="dipole-dipole",
        choices=["dipole-dipole", "pole-dipole", "dipole-pole", "pole-pole"],
    )

    dimension = properties.Integer("Dimension of electrode locations",
                                   default=2,
                                   required=True)

    a_locations = properties.Array(
        "locations of the positive (+) current electrodes",
        required=True,
        shape=("*", "*"),  # ('*', 3) for 3D or ('*', 2) for 2D
        dtype=float,  # data are floats
    )

    b_locations = properties.Array(
        "locations of the negative (-) current electrodes",
        required=True,
        shape=("*", "*"),  # ('*', 3) for 3D or ('*', 2) for 2D
        dtype=float,  # data are floats
    )

    m_locations = properties.Array(
        "locations of the positive (+) potential electrodes",
        required=True,
        shape=("*", "*"),  # ('*', 3) for 3D or ('*', 2) for 2D
        dtype=float,  # data are floats
    )

    n_locations = properties.Array(
        "locations of the negative (-) potential electrodes",
        required=True,
        shape=("*", "*"),  # ('*', 3) for 3D or ('*', 2) for 2D
        dtype=float,  # data are floats
    )

    electrode_locations = properties.Array(
        "unique locations of a, b, m, n electrodes",
        required=True,
        shape=("*", "*"),  # ('*', 3) for 3D or ('*', 2) for 2D
        dtype=float,  # data are floats
    )

    # Data
    data_dc_type = properties.StringChoice(
        "Type of DC-IP survey",
        required=True,
        default="volt",
        choices=[
            "volt",
            "apparent_resistivity",
            "apparent_conductivity",
        ],
    )

    data_dc = properties.Array(
        "Measured DC data",
        shape=("*", ),
        dtype=float  # data are floats
    )

    data_ip_type = properties.StringChoice(
        "Type of DC-IP survey",
        required=True,
        default="volt",
        choices=[
            "volt",
            "apparent_chargeability",
        ],
    )

    data_ip = properties.Array(
        "Measured IP data",
        shape=("*", ),
        dtype=float  # data are floats
    )

    data_sip_type = properties.StringChoice(
        "Type of DC-IP survey",
        required=True,
        default="volt",
        choices=[
            "volt",
            "apparent_chargeability",
        ],
    )

    data_sip = properties.Array(
        "Measured Spectral IP data",
        shape=("*", "*"),
        dtype=float  # data are floats
    )

    times_ip = properties.Array(
        "Time channels of measured Spectral IP voltages (s)",
        required=True,
        shape=("*", ),
        dtype=float,  # data are floats
    )

    G = properties.Array(
        "Geometric factor of DC-IP survey",
        shape=("*", ),
        dtype=float  # data are floats
    )

    grids = properties.Array(
        "Spatial grids for plotting pseudo-section",
        shape=("*", "*"),
        dtype=float,  # data are floats
    )

    space_type = properties.StringChoice(
        "Assumption to compute apparent resistivity",
        default="half-space",
        choices=["half-space", "whole-space"],
    )

    line_inds = properties.Array(
        "Line indices",
        required=True,
        shape=("*", ),
        dtype=int  # data are floats
    )
    sort_inds = properties.Array(
        "Sorting indices from ABMN",
        required=True,
        shape=("*", ),
        dtype=int,  # data are floats
    )

    # Related to Physics and Discretization
    mesh = properties.Instance("Mesh for discretization",
                               BaseMesh,
                               required=True)

    dx = properties.Float(
        "Length of corecell in x-direction",
        required=True,
    )
    dy = properties.Float("Length of corecell in y-direction", required=True)
    dz = properties.Float("Length of corecell in z-direction", required=True)

    npad_x = properties.Integer("The number of padding cells x-direction",
                                required=True,
                                default=5)

    npad_y = properties.Integer("The number of padding cells y-direction",
                                required=True,
                                default=5)

    npad_z = properties.Integer("The number of padding cells z-direction",
                                required=True,
                                default=5)

    pad_rate_x = properties.Float(
        "Expansion rate of padding cells in  x-direction",
        required=True,
        default=1.3)

    pad_rate_y = properties.Float(
        "Expansion rate of padding cells in  y-direction",
        required=True,
        default=1.3)

    pad_rate_z = properties.Float(
        "Expansion rate of padding cells in  z-direction",
        required=True,
        default=1.3)

    ncell_per_dipole = properties.Integer(
        "The number of cells between dipole electrodes",
        required=True,
        default=4)

    corezlength = properties.Float(
        "Core depth (m)",
        required=True,
    )

    # For synthetic surveys
    x0 = None
    lineLength = None
    a = None
    n_spacing = None
    n_data = None

    def __init__(self, **kwargs):
        super(IO, self).__init__(**kwargs)
        warnings.warn(
            "code under construction - API might change in the future")

    # Properties
    @property
    def voltages(self):
        """
        Votages (V)
        """
        if self.data_dc_type.lower() == "volt":
            return self.data_dc
        elif self.data_dc_type.lower() == "apparent_resistivity":
            return self.data_dc * self.G
        elif self.data_dc_type.lower() == "apparent_conductivity":
            return self.apparent_conductivity / (self.data_dc * self.G)
        else:
            raise NotImplementedError()

    @property
    def apparent_resistivity(self):
        """
        Apparent Resistivity (Ohm-m)
        """
        if self.data_dc_type.lower() == "apparent_resistivity":
            return self.data_dc
        elif self.data_dc_type.lower() == "volt":
            return self.data_dc / self.G
        elif self.data_dc_type.lower() == "apparent_conductivity":
            return 1.0 / self.data_dc
        else:
            print(self.data_dc_type.lower())
            raise NotImplementedError()

    @property
    def apparent_conductivity(self):
        """
        Apparent Conductivity (S/m)
        """
        if self.data_dc_type.lower() == "apparent_conductivity":
            return self.data_dc
        elif self.data_dc_type.lower() == "apparent_resistivity":
            return 1.0 / self.data_dc
        elif self.data_dc_type.lower() == "volt":
            return 1.0 / self.data_dc * self.G

    # For IP
    @property
    def voltages_ip(self):
        """
        IP votages (V)
        """
        if self.data_ip_type.lower() == "volt":
            return self.data_ip
        elif self.data_ip_type.lower() == "apparent_chargeability":
            if self.voltages is None:
                raise Exception(
                    "DC voltages must be set to compute IP voltages")
            return self.data_ip * self.voltages
        else:
            raise NotImplementedError()

    # For SIP
    @property
    def voltages_sip(self):
        """
        IP votages (V)
        """
        if self.data_sip_type.lower() == "volt":
            return self.data_sip
        elif self.data_sip_type.lower() == "apparent_chargeability":
            if self.voltages is None:
                raise Exception(
                    "DC voltages must be set to compute IP voltages")
            return sdiag(self.voltages) * self.data_sip
        else:
            raise NotImplementedError()

    @property
    def apparent_chargeability(self):
        """
        Apparent Conductivity (S/m)
        """
        if self.data_ip_type.lower() == "apparent_chargeability":
            return self.data_ip
        elif self.data_ip_type.lower() == "volt":
            if self.voltages is None:
                raise Exception(
                    "DC voltages must be set to compute Apparent Chargeability"
                )
            return self.data_ip / self.voltages
        else:
            raise NotImplementedError()

    # For SIP
    @property
    def apparent_chargeability_sip(self):
        """
        Apparent Conductivity (S/m)
        """
        if self.data_sip_type.lower() == "apparent_chargeability":
            return self.data_sip
        elif self.data_sip_type.lower() == "volt":
            if self.voltages is None:
                raise Exception(
                    "DC voltages must be set to compute Apparent Chargeability"
                )
            return sdiag(1.0 / self.voltages) * self.data_sip
        else:
            raise NotImplementedError()

    def geometric_factor(self, survey):
        """
        Compute geometric factor, G, using locational informaition
        in survey object
        """
        G = geometric_factor(survey, space_type=self.space_type)
        return G

    def from_ambn_locations_to_survey(self, *args, **kwargs):
        warnings.warn(
            "from_ambn_locations_to_survey has been renamed to "
            "from_abmn_locations_to_survey. It will be removed in a future version 0.17.0 of simpeg",
            DeprecationWarning,
        )
        return self.from_abmn_locations_to_survey(*args, **kwargs)

    def from_abmn_locations_to_survey(
        self,
        a_locations,
        b_locations,
        m_locations,
        n_locations,
        survey_type=None,
        data_dc=None,
        data_ip=None,
        data_sip=None,
        data_dc_type="volt",
        data_ip_type="volt",
        data_sip_type="volt",
        fname=None,
        dimension=2,
        line_inds=None,
        times_ip=None,
    ):
        """
        read A, B, M, N electrode location and data (V or apparent_resistivity)
        """
        self.a_locations = a_locations.copy()
        self.b_locations = b_locations.copy()
        self.m_locations = m_locations.copy()
        self.n_locations = n_locations.copy()
        self.survey_type = survey_type
        self.dimension = dimension
        self.data_dc_type = data_dc_type
        self.data_ip_type = data_ip_type
        self.data_sip_type = data_sip_type
        if times_ip is not None:
            self.times_ip = times_ip

        uniqSrc = uniqueRows(np.c_[self.a_locations, self.b_locations])
        uniqElec = uniqueRows(
            np.vstack((self.a_locations, self.b_locations, self.m_locations,
                       self.n_locations)))
        self.electrode_locations = uniqElec[0]
        nSrc = uniqSrc[0].shape[0]
        ndata = self.a_locations.shape[0]

        if self.survey_layout == "SURFACE":
            # 2D locations
            srcLists = []
            sort_inds = []
            for iSrc in range(nSrc):
                inds = uniqSrc[2] == iSrc
                sort_inds.append(np.arange(ndata)[inds])

                locsM = self.m_locations[inds, :]
                locsN = self.n_locations[inds, :]
                if survey_type in ["dipole-dipole", "pole-dipole"]:
                    rx = Rx.Dipole(locsM, locsN)
                elif survey_type in ["dipole-pole", "pole-pole"]:
                    rx = Rx.Pole(locsM)
                else:
                    raise NotImplementedError()

                if dimension == 2:
                    locA = uniqSrc[0][iSrc, :2]
                    locB = uniqSrc[0][iSrc, 2:]
                elif dimension == 3:
                    locA = uniqSrc[0][iSrc, :3]
                    locB = uniqSrc[0][iSrc, 3:]

                if survey_type in ["dipole-dipole", "dipole-pole"]:
                    src = Src.Dipole([rx], locA, locB)
                elif survey_type in ["pole-dipole", "pole-pole"]:
                    src = Src.Pole([rx], locA)

                srcLists.append(src)

            self.sort_inds = np.hstack(sort_inds)

            if dimension == 2:
                survey = Survey(srcLists)
            elif dimension == 3:
                survey = Survey(srcLists)
            else:
                raise NotImplementedError()

            self.a_locations = self.a_locations[self.sort_inds, :]
            self.b_locations = self.b_locations[self.sort_inds, :]
            self.m_locations = self.m_locations[self.sort_inds, :]
            self.n_locations = self.n_locations[self.sort_inds, :]
            self.G = self.geometric_factor(survey)

            if data_dc is not None:
                self.data_dc = data_dc[self.sort_inds]
            if data_ip is not None:
                self.data_ip = data_ip[self.sort_inds]
            if data_sip is not None:
                self.data_sip = data_sip[self.sort_inds, :]
            if line_inds is not None:
                self.line_inds = line_inds[self.sort_inds]
            # Here we ignore ... z-locations
            self.n_data = survey.nD

            midABx = (self.a_locations[:, 0] + self.b_locations[:, 0]) * 0.5
            midMNx = (self.m_locations[:, 0] + self.n_locations[:, 0]) * 0.5

            if dimension == 2:
                z = abs(midABx - midMNx) * 1.0 / 3.0
                x = (midABx + midMNx) * 0.5
                zmax = z.max()
                a = abs(np.diff(np.sort(self.electrode_locations[:, 0]))).min()
                # Consider the case of 1D types of array
                if np.all(zmax < a):
                    z = abs(self.a_locations[:, 0] -
                            self.b_locations[:, 0]) / 3.0
                self.grids = np.c_[x, z]

            elif dimension == 3:
                midABy = (self.a_locations[:, 1] +
                          self.b_locations[:, 1]) * 0.5
                midMNy = (self.m_locations[:, 1] +
                          self.n_locations[:, 1]) * 0.5
                z = np.sqrt((midABx - midMNx)**2 +
                            (midABy - midMNy)**2) * 1.0 / 3.0
                x = (midABx + midMNx) * 0.5
                y = (midABy + midMNy) * 0.5
                self.grids = np.c_[x, y, z]
            else:
                raise Exception()
        else:
            raise NotImplementedError()
        return survey

    def set_mesh(
        self,
        topo=None,
        dx=None,
        dy=None,
        dz=None,
        corezlength=None,
        npad_x=None,
        npad_y=None,
        npad_z=None,
        pad_rate_x=None,
        pad_rate_y=None,
        pad_rate_z=None,
        ncell_per_dipole=None,
        mesh_type="TensorMesh",
        dimension=2,
        method="nearest",
    ):
        """
        Set up a mesh for a given DC survey
        """

        # Update properties
        if npad_x is None:
            npad_x = self.npad_x
        self.npad_x = npad_x

        if npad_z is None:
            npad_z = self.npad_z
        self.npad_z = npad_z

        if pad_rate_x is None:
            pad_rate_x = self.pad_rate_x
        self.pad_rate_x = pad_rate_x

        if pad_rate_z is None:
            pad_rate_z = self.pad_rate_z
        self.pad_rate_z = pad_rate_z

        if ncell_per_dipole is None:
            ncell_per_dipole = self.ncell_per_dipole
        self.ncell_per_dipole = ncell_per_dipole

        # 2D or 3D mesh
        if dimension not in [2, 3]:
            raise NotImplementedError(
                "Set mesh has not been implemented for a 1D system")

        if dimension == 2:
            z_ind = 1
        else:
            z_ind = 2
        a = abs(np.diff(np.sort(self.electrode_locations[:, 0]))).min()
        lineLength = abs(self.electrode_locations[:, 0].max() -
                         self.electrode_locations[:, 0].min())
        dx_ideal = a / ncell_per_dipole
        if dx is None:
            dx = dx_ideal
            print("dx is set to {} m (samllest electrode spacing ({}) / {})".
                  format(dx, a, ncell_per_dipole))
        if dz is None:
            dz = dx * 0.5
            print("dz ({} m) is set to dx ({} m) / {}".format(dz, dx, 2))
        if dimension == 3:
            if dy is None:
                print("dy is set equal to dx")
                dy = dx
            self.dy = dy

            if npad_y is None:
                npad_y = self.npad_y
            self.npad_y = npad_y

            if pad_rate_y is None:
                pad_rate_y = self.pad_rate_y
            self.pad_rate_y = pad_rate_y

        x0 = self.electrode_locations[:, 0].min()
        if topo is None:
            # For 2D mesh
            if dimension == 2:
                # sort by x
                row_idx = np.lexsort((self.electrode_locations[:, 0], ))
            # For 3D mesh
            else:
                # sort by x, then by y
                row_idx = np.lexsort(
                    (self.electrode_locations[:,
                                              1], self.electrode_locations[:,
                                                                           0]))
            locs = self.electrode_locations[row_idx, :]
        else:
            # For 2D mesh
            if dimension == 2:
                mask = np.isin(self.electrode_locations[:, 0], topo[:, 0])
                if np.any(mask):
                    warnings.warn(
                        "Because the x coordinates of some topo and electrodes are the same,"
                        " we excluded electrodes with the same coordinates.",
                        RuntimeWarning,
                    )
                locs_tmp = np.vstack(
                    (topo, self.electrode_locations[~mask, :]))
                row_idx = np.lexsort((locs_tmp[:, 0], ))
            else:
                dtype = [("x", np.float64), ("y", np.float64)]
                mask = np.isin(
                    self.electrode_locations[:, [0, 1]].copy().view(dtype),
                    topo[:, [0, 1]].copy().view(dtype),
                ).flatten()
                if np.any(mask):
                    warnings.warn(
                        "Because the x and y coordinates of some topo and electrodes are the same,"
                        " we excluded electrodes with the same coordinates.",
                        RuntimeWarning,
                    )
                locs_tmp = np.vstack(
                    (topo, self.electrode_locations[~mask, :]))
                row_idx = np.lexsort((locs_tmp[:, 1], locs_tmp[:, 0]))
            locs = locs_tmp[row_idx, :]

        if dx > dx_ideal:
            # warnings.warn(
            #     "Input dx ({}) is greater than expected \n We recommend using {:0.1e} m cells, that is, {} cells per {0.1e} m dipole length".format(dx, dx_ideal, ncell_per_dipole, a)
            # )
            pass

        # Set mesh properties to class instance
        self.dx = dx
        self.dz = dz

        zmax = locs[:, z_ind].max()
        zmin = locs[:, z_ind].min()

        # 3 cells each for buffer
        corexlength = lineLength + dx * 6
        if corezlength is None:
            dz_topo = locs[:, 1].max() - locs[:, 1].min()
            corezlength = self.grids[:, z_ind].max() + dz_topo
            self.corezlength = corezlength

        if mesh_type == "TensorMesh":
            ncx = np.round(corexlength / dx)
            ncz = np.round(corezlength / dz)
            hx = [(dx, npad_x, -pad_rate_x), (dx, ncx),
                  (dx, npad_x, pad_rate_x)]
            hz = [(dz, npad_z, -pad_rate_z), (dz, ncz)]
            x0_mesh = -(
                (dx * pad_rate_x**(np.arange(npad_x) + 1)).sum() + dx * 3 - x0)
            z0_mesh = (-(
                (dz * pad_rate_z**(np.arange(npad_z) + 1)).sum() + dz * ncz) +
                       zmax)

            # For 2D mesh
            if dimension == 2:
                h = [hx, hz]
                x0_for_mesh = [x0_mesh, z0_mesh]
                self.xyzlim = np.vstack(
                    (np.r_[x0, x0 + lineLength], np.r_[zmax - corezlength,
                                                       zmax]))
                fill_value = "extrapolate"

            # For 3D mesh
            else:

                ylocs = np.unique(self.electrode_locations[:, 1])
                ymin, ymax = ylocs.min(), ylocs.max()
                # 3 cells each for buffer in y-direction
                coreylength = ymax - ymin + dy * 6
                ncy = np.round(coreylength / dy)
                hy = [(dy, npad_y, -pad_rate_y), (dy, ncy),
                      (dy, npad_y, pad_rate_y)]
                y0 = ylocs.min() - dy / 2.0
                y0_mesh = -((dy * pad_rate_y**(np.arange(npad_y) + 1)).sum() +
                            dy * 3 - y0)

                h = [hx, hy, hz]
                x0_for_mesh = [x0_mesh, y0_mesh, z0_mesh]
                self.xyzlim = np.vstack((
                    np.r_[x0, x0 + lineLength],
                    np.r_[ymin - dy * 3, ymax + dy * 3],
                    np.r_[zmax - corezlength, zmax],
                ))
            mesh = TensorMesh(h, x0=x0_for_mesh)

        elif mesh_type == "TREE":
            # Quadtree mesh
            if dimension == 2:

                pad_length_x = np.sum(meshTensor([(dx, npad_x, pad_rate_x)]))
                pad_length_z = np.sum(meshTensor([(dz, npad_z, pad_rate_z)]))

                dom_width_x = lineLength + 2 * pad_length_x  # domain width x
                dom_width_z = corezlength + pad_length_z  # domain width z

                nbcx = 2**int(np.ceil(np.log(dom_width_x / dx) /
                                      np.log(2.0)))  # num. base cells x
                nbcz = 2**int(np.ceil(np.log(dom_width_z / dz) /
                                      np.log(2.0)))  # num. base cells z

                length = 0.0
                dz_tmp = dz
                octree_levels = []
                while length < corezlength:
                    length += 5 * dz_tmp
                    octree_levels.append(5)
                    dz_tmp *= 2

                # Define the base mesh
                hx = [(dx, nbcx)]
                hz = [(dz, nbcz)]

                mesh_width = np.sum(meshTensor(hx))
                mesh_height = np.sum(meshTensor(hz))

                array_midpoint = 0.5 * (self.electrode_locations[:, 0].min() +
                                        self.electrode_locations[:, 0].max())
                mesh = TreeMesh(
                    [hx, hz],
                    x0=[array_midpoint - mesh_width / 2, zmax - mesh_height])
                # mesh = TreeMesh([hx, hz], x0='CN')

                # Mesh refinement based on topography
                mesh = refine_tree_xyz(
                    mesh,
                    self.electrode_locations,
                    octree_levels=octree_levels,
                    method="radial",
                    finalize=False,
                )
                mesh.finalize()

                self.xyzlim = np.vstack((
                    np.r_[self.electrode_locations[:, 0].min(),
                          self.electrode_locations[:, 0].max(), ],
                    np.r_[zmax - corezlength, zmax],
                ))

            # Octree mesh
            elif dimension == 3:
                raise NotImplementedError(
                    "set_mesh has not implemented 3D TreeMesh (yet)")

        else:
            raise NotImplementedError(
                "set_mesh currently generates TensorMesh or TreeMesh")

        actind = surface2ind_topo(mesh, locs, method=method, fill_value=np.nan)

        return mesh, actind

    def plotPseudoSection(
        self,
        data_type="apparent_resistivity",
        data=None,
        dataloc=True,
        aspect_ratio=2,
        scale="log",
        cmap="viridis",
        ncontour=10,
        ax=None,
        figname=None,
        clim=None,
        label=None,
        iline=0,
        orientation="vertical",
    ):
        """
        Plot 2D pseudo-section for DC-IP data
        """
        matplotlib.rcParams["font.size"] = 12

        if ax is None:
            fig = plt.figure(figsize=(10, 5))
            ax = plt.subplot(111)

        if self.dimension == 2:
            inds = np.ones(self.n_data, dtype=bool)
            grids = self.grids.copy()
        elif self.dimension == 3:
            inds = self.line_inds == iline
            grids = self.grids[inds, :][:, [0, 2]]
        else:
            raise NotImplementedError()

        if data_type == "apparent_resistivity":
            if data is None:
                val = self.apparent_resistivity[inds]
            else:
                val = data.copy()[inds]
            label_tmp = "Apparent Res. ($\Omega$m)"
        elif data_type == "volt":
            if data is None:
                val = self.voltages[inds]
            else:
                val = data.copy()[inds]
            label_tmp = "Voltage (V)"
        elif data_type == "apparent_conductivity":
            if data is None:
                val = self.apparent_conductivity[inds]
            else:
                val = data.copy()[inds]
            label_tmp = "Apparent Cond. (S/m)"
        elif data_type == "apparent_chargeability":
            if data is not None:
                val = data.copy()[inds]
            else:
                val = self.apparent_chargeability.copy()[inds] * 1e3
            label_tmp = "Apparent Charg. (mV/V)"
        elif data_type == "volt_ip":
            if data is not None:
                val = data.copy()[inds]
            else:
                val = self.voltages_ip.copy()[inds] * 1e3
            label_tmp = "Secondary voltage. (mV)"
        else:
            print(data_type)
            raise NotImplementedError()

        if label is None:
            label = label_tmp

        out = plot2Ddata(
            grids,
            val,
            contourOpts={"cmap": cmap},
            ax=ax,
            dataloc=dataloc,
            scale=scale,
            ncontour=ncontour,
            clim=clim,
        )
        ax.invert_yaxis()
        ax.set_xlabel("x (m)")
        ax.set_yticklabels([])
        ax.set_ylabel("n-spacing")
        if orientation == "vertical":
            frac = 0.01
        elif orientation == "horizontal":
            frac = 0.03
        else:
            raise ValueError(
                "Orientation must be either vertical or horizontal, not {}".
                format(orientation))
        cb = plt.colorbar(out[0],
                          format="%.1e",
                          ax=ax,
                          orientation=orientation,
                          fraction=frac)
        cb.set_label(label)
        cb.set_ticks(out[0].levels)
        ax.set_aspect(aspect_ratio)
        plt.tight_layout()
        if figname is not None:
            fig.savefig(figname, dpi=200)

    def read_ubc_dc2d_obs_file(self,
                               filename,
                               input_type="simple",
                               toponame=None):
        obsfile = np.genfromtxt(filename,
                                delimiter=" \n",
                                dtype=np.str,
                                comments="!")
        if input_type == "general":
            topo = None
            n_src = 0
            n_rxs = []
            src_info = []
            abmn = []
            for obs in obsfile:
                temp = np.fromstring(obs, dtype=float, sep=" ").T
                if len(temp) == 5:
                    n_src += 1
                    src_info = temp[:4]
                    n_rxs.append(int(temp[-1]))
                else:
                    abmn.append(np.r_[src_info, temp])

            abmn = np.vstack(abmn)
            a = np.c_[abmn[:, 0], -abmn[:, 1]]
            b = np.c_[abmn[:, 2], -abmn[:, 3]]
            m = np.c_[abmn[:, 4], -abmn[:, 5]]
            n = np.c_[abmn[:, 6], -abmn[:, 7]]
            voltage = abmn[:, 8]
            standard_deviation = abmn[:, 9]

        elif input_type == "simple":
            if toponame is not None:
                tmp_topo = np.loadtxt(toponame)
                n_topo = tmp_topo[0, 0]
                z_ref = tmp_topo[0, 1]
                topo = tmp_topo[1:, :]
                if topo.shape[0] != n_topo:
                    print(
                        ">> # of points for the topography is not {0}, but {0}"
                        .format(n_topo, topo.shape[0]))
            tmp = np.loadtxt(filename, comments="!").astype(float)
            e = np.zeros(tmp.shape[0], dtype=float)
            a = np.c_[tmp[:, 0], e]
            b = np.c_[tmp[:, 1], e]
            m = np.c_[tmp[:, 2], e]
            n = np.c_[tmp[:, 3], e]
            voltage = tmp[:, 4]
            standard_deviation = tmp[:, 5]

        if np.all(a == b):
            if np.all(m == n):
                survey_type = "pole-pole"
            else:
                survey_type = "pole-dipole"
        else:
            if np.all(m == n):
                survey_type = "dipole-pole"
            else:
                survey_type = "dipole-dipole"

        survey = self.from_abmn_locations_to_survey(a,
                                                    b,
                                                    m,
                                                    n,
                                                    survey_type=survey_type,
                                                    data_dc=voltage)
        survey.dobs = voltage[self.sort_inds]
        survey.std = standard_deviation[self.sort_inds]
        survey.topo = topo
        return survey

    def write_to_csv(self, fname, dobs, standard_deviation=None, **kwargs):
        uncert = kwargs.pop("uncertainty", None)
        if uncert is not None:
            warnings.warn(
                "The uncertainty option has been deprecated and will be removed"
                " in SimPEG 0.16.0. Please use standard_deviation.",
                FutureWarning,
            )
            standard_deviation = uncert

        if standard_deviation is None:
            standard_deviation = np.ones(dobs.size) * np.nan
        data = np.c_[self.a_locations, self.b_locations, self.m_locations,
                     self.n_locations, dobs, standard_deviation, ]
        df = pd.DataFrame(
            data=data,
            columns=[
                "Ax",
                "Az",
                "Bx",
                "Bz",
                "Mx",
                "Mz",
                "Nx",
                "Nz",
                "Voltage",
                "Uncertainty",
            ],
        )
        df.to_csv(fname)

    def read_dc_data_csv(self, fname, dim=2):
        df = pd.read_csv(fname)
        if dim == 2:
            a_locations = df[["Ax", "Az"]].values
            b_locations = df[["Bx", "Bz"]].values
            m_locations = df[["Mx", "Mz"]].values
            n_locations = df[["Nx", "Nz"]].values
            dobs = df["Voltage"].values
            standard_deviation = df["Uncertainty"].values

            if np.all(a_locations == b_locations):
                src_type = "pole-"
            else:
                src_type = "dipole-"

            if np.all(m_locations == n_locations):
                rx_type = "pole"
            else:
                rx_type = "dipole"
            survey_type = src_type + rx_type
            survey = self.from_abmn_locations_to_survey(
                a_locations,
                b_locations,
                m_locations,
                n_locations,
                survey_type,
                data_dc=dobs,
                data_dc_type="volt",
            )
            survey.std = standard_deviation[self.sort_inds]
            survey.dobs = dobs[self.sort_inds]
        else:
            raise NotImplementedError()
        return survey

    def read_topo_csv(self, fname, dim=2):
        if dim == 2:
            df = pd.read_csv(fname)
            topo = df[["X", "Z"]].values
        return topo
Ejemplo n.º 20
0
 class HasInt(properties.HasProperties):
     myint = properties.Integer('my integer')
Ejemplo n.º 21
0
    def _test_dict(self, om):

        with self.assertRaises(TypeError):
            properties.Dictionary('bad string set', key_prop=str)
        with self.assertRaises(TypeError):
            properties.Dictionary('bad string set', value_prop=str)
        with self.assertRaises(TypeError):
            properties.Dictionary('bad observe',
                                  properties.Integer(''),
                                  observe_mutations=5)

        class HasPropsDummy(properties.HasProperties):
            pass

        mydict = properties.Dictionary('dummy has properties set',
                                       key_prop=properties.String(''),
                                       value_prop=HasPropsDummy,
                                       observe_mutations=om)
        assert isinstance(mydict.key_prop, properties.String)
        assert isinstance(mydict.value_prop, properties.Instance)
        assert mydict.value_prop.instance_class is HasPropsDummy

        class HasDummyDict(properties.HasProperties):
            mydict = properties.Dictionary('dummy has properties set',
                                           key_prop=properties.String(''),
                                           value_prop=HasPropsDummy,
                                           observe_mutations=om)

        assert HasDummyDict()._props['mydict'].name == 'mydict'
        assert HasDummyDict()._props['mydict'].key_prop.name == 'mydict'
        assert HasDummyDict()._props['mydict'].value_prop.name == 'mydict'

        class HasDict(properties.HasProperties):
            aaa = properties.Dictionary('dictionary', default=dict)

        li = HasDict()
        li.aaa = {1: 2}
        with self.assertRaises(ValueError):
            li.aaa = (1, 2, 3)
        li.aaa = {'hi': HasPropsDummy()}
        with self.assertRaises(ValueError):
            li.aaa = 4
        with self.assertRaises(ValueError):
            li.aaa = {'a', 'b', 'c'}

        li1 = HasDict()
        li2 = HasDict()
        assert li1.aaa == li2.aaa
        assert li1.aaa is not li2.aaa

        class HasInt(properties.HasProperties):
            myint = properties.Integer('my integer')

        class HasFunnyDict(properties.HasProperties):
            mydict = properties.Dictionary('my dict',
                                           key_prop=properties.Color(''),
                                           value_prop=HasInt,
                                           observe_mutations=om)

        hfd = HasFunnyDict()
        hfd.mydict = {'red': HasInt(myint=5)}
        hfd.mydict.update({'green': HasInt(myint=1)})

        if om:
            hfd.validate()
        else:
            with self.assertRaises(ValueError):
                hfd.validate()

        with self.assertRaises(ValueError):
            hfd.mydict.update({1: HasInt(myint=1)})
            hfd.validate()

        class HasCoercedDict(properties.HasProperties):
            my_coerced_dict = properties.Dictionary('my dict', coerce=True)
            my_uncoerced_dict = properties.Dictionary('my dict')

        key_val_list = [('a', 1), ('b', 2), ('c', 3)]

        hcd = HasCoercedDict()
        with self.assertRaises(ValueError):
            hcd.my_uncoerced_dict = key_val_list

        hcd.my_coerced_dict = key_val_list
        assert hcd.my_coerced_dict == {'a': 1, 'b': 2, 'c': 3}

        with self.assertRaises(properties.ValidationError):
            hcd.my_coerced_dict = 'a'
Ejemplo n.º 22
0
 class HasCoercedIntTuple(properties.HasProperties):
     aaa = properties.Tuple('tuple of ints',
                            properties.Integer(''),
                            coerce=True)
Ejemplo n.º 23
0
 class HasIntTuple(properties.HasProperties):
     aaa = properties.Tuple('tuple of ints',
                            properties.Integer(''),
                            default=tuple)
Ejemplo n.º 24
0
 class HasIntA(properties.HasProperties):
     a = properties.Integer('int a', required=True)
Ejemplo n.º 25
0
 class HasConstrianedSet(properties.HasProperties):
     aaa = properties.Set('set of ints',
                          properties.Integer(''),
                          max_length=2,
                          observe_mutations=om)
Ejemplo n.º 26
0
 class HasCoercedIntSet(properties.HasProperties):
     aaa = properties.Set('set of ints',
                          properties.Integer(''),
                          observe_mutations=om,
                          coerce=True)
Ejemplo n.º 27
0
 class HasIntSet(properties.HasProperties):
     aaa = properties.Set('set of ints',
                          properties.Integer(''),
                          observe_mutations=om,
                          default=set)
Ejemplo n.º 28
0
    def _test_set(self, om):

        with self.assertRaises(TypeError):
            properties.Set('bad string set', prop=str)
        with self.assertRaises(TypeError):
            properties.Set('bad max', properties.Integer(''), max_length=-10)
        with self.assertRaises(TypeError):
            properties.Set('bad max', properties.Integer(''), max_length='ten')
        with self.assertRaises(TypeError):
            myset = properties.Set('bad max',
                                   properties.Integer(''),
                                   min_length=20)
            myset.max_length = 10
        with self.assertRaises(TypeError):
            properties.Set('bad min', properties.Integer(''), min_length=-10)
        with self.assertRaises(TypeError):
            properties.Set('bad min', properties.Integer(''), min_length='ten')
        with self.assertRaises(TypeError):
            myset = properties.Set('bad min',
                                   properties.Integer(''),
                                   max_length=10)
            myset.min_length = 20
        with self.assertRaises(TypeError):
            properties.Set('bad observe',
                           properties.Integer(''),
                           observe_mutations=5)
        with self.assertRaises(TypeError):
            properties.Set('bad coerce', properties.Integer(''), coerce=5)

        class HasPropsDummy(properties.HasProperties):
            pass

        myset = properties.Set('dummy has properties set',
                               prop=HasPropsDummy,
                               observe_mutations=om)
        assert isinstance(myset.prop, properties.Instance)
        assert myset.prop.instance_class is HasPropsDummy

        class HasDummySet(properties.HasProperties):
            myset = properties.Set('dummy has properties set',
                                   prop=HasPropsDummy,
                                   observe_mutations=om)

        assert HasDummySet()._props['myset'].name == 'myset'
        assert HasDummySet()._props['myset'].prop.name == 'myset'

        class HasIntSet(properties.HasProperties):
            aaa = properties.Set('set of ints',
                                 properties.Integer(''),
                                 observe_mutations=om,
                                 default=set)

        li = HasIntSet()
        li.aaa = {1, 2, 3}
        with self.assertRaises(ValueError):
            li.aaa = (1, 2, 3)
        li.aaa = {1., 2., 3.}
        with self.assertRaises(ValueError):
            li.aaa = 4
        with self.assertRaises(ValueError):
            li.aaa = {'a', 'b', 'c'}

        li1 = HasIntSet()
        li2 = HasIntSet()
        assert li1.aaa == li2.aaa
        assert li1.aaa is not li2.aaa

        class HasCoercedIntSet(properties.HasProperties):
            aaa = properties.Set('set of ints',
                                 properties.Integer(''),
                                 observe_mutations=om,
                                 coerce=True)

        li = HasCoercedIntSet()
        li.aaa = 1
        assert li.aaa == {1}
        li.aaa = [1, 2, 3]
        assert li.aaa == {1, 2, 3}
        li.aaa = (1, 2, 3)
        assert li.aaa == {1, 2, 3}

        class HasConstrianedSet(properties.HasProperties):
            aaa = properties.Set('set of ints',
                                 properties.Integer(''),
                                 min_length=2,
                                 observe_mutations=om)

        li = HasConstrianedSet()
        li.aaa = {1, 2, 3}
        li.validate()
        li.aaa = {1}
        with self.assertRaises(ValueError):
            li.validate()

        class HasConstrianedSet(properties.HasProperties):
            aaa = properties.Set('set of ints',
                                 properties.Integer(''),
                                 max_length=2,
                                 observe_mutations=om)

        li = HasConstrianedSet()
        li.aaa = {1, 2}
        li.validate()
        li.aaa = {1, 2, 3, 4, 5}
        with self.assertRaises(ValueError):
            li.validate()

        class HasColorSet(properties.HasProperties):
            ccc = properties.Set('set of colors',
                                 properties.Color(''),
                                 observe_mutations=om)

        li = HasColorSet()
        li.ccc = {'red', '#00FF00'}
        assert li.ccc == {(255, 0, 0), (0, 255, 0)}

        numset = {1, 2, 3, 4}
        assert properties.Set.to_json(numset) == list(numset)
        assert properties.Set.from_json(list(numset)) == numset
        assert properties.Set.from_json(list(numset)) is not numset

        class HasIntA(properties.HasProperties):
            a = properties.Integer('int a', required=True)

        hia_json = properties.Set.to_json({HasIntA(a=5), HasIntA(a=10)})
        assert (hia_json == [{
            '__class__': 'HasIntA',
            'a': 5
        }, {
            '__class__': 'HasIntA',
            'a': 10
        }] or hia_json == [{
            '__class__': 'HasIntA',
            'a': 10
        }, {
            '__class__': 'HasIntA',
            'a': 5
        }])

        li_ser = li.serialize(include_class=False)
        assert (li_ser == {
            'ccc': [[255, 0, 0], [0, 255, 0]]
        } or li_ser == {
            'ccc': [[0, 255, 0], [255, 0, 0]]
        })

        class HasIntASet(properties.HasProperties):
            myset = properties.Set('set of HasIntA',
                                   HasIntA,
                                   observe_mutations=om)

        deser_set = HasIntASet.deserialize({
            'myset': [{
                'a': 0
            }, {
                'a': 10
            }, {
                'a': 100
            }]
        }).myset
        assert isinstance(deser_set, set)
        assert len(deser_set) == 3
        assert all(isinstance(val, HasIntA) for val in deser_set)
        assert {val.a for val in deser_set} == {0, 10, 100}

        class HasOptionalSet(properties.HasProperties):
            myset = properties.Set('',
                                   properties.Bool(''),
                                   required=False,
                                   observe_mutations=om)

        hol = HasOptionalSet()
        hol.validate()

        assert HasIntASet._props['myset'].deserialize(None) is None

        assert properties.Set('',
                              properties.Instance('', HasIntA),
                              observe_mutations=om).equal(
                                  {HasIntA(a=1), HasIntA(a=2)},
                                  {HasIntA(a=1), HasIntA(a=2)})
        assert not properties.Set(
            '', properties.Instance('', HasIntA), observe_mutations=om).equal(
                {HasIntA(a=1), HasIntA(a=2)},
                {HasIntA(a=1), HasIntA(a=2),
                 HasIntA(a=3)})
        assert not properties.Set(
            '', properties.Instance('', HasIntA), observe_mutations=om).equal(
                {HasIntA(a=1), HasIntA(a=2)},
                {HasIntA(a=1), HasIntA(a=3)})
        assert not properties.Set(
            '', properties.Integer(''), observe_mutations=om).equal(5, 5)
Ejemplo n.º 29
0
 class HasConstrianedList(properties.HasProperties):
     aaa = properties.List('list of ints',
                           properties.Integer(''),
                           min_length=2,
                           observe_mutations=om)
Ejemplo n.º 30
0
 class HasIntList(properties.HasProperties):
     aaa = properties.List('list of ints',
                           properties.Integer(''),
                           observe_mutations=om,
                           default=list)