Beispiel #1
0
class Workflow(BaseModel):

    mailbox_id = properties.Integer(
        'The mailbox ID that this workflow is associated with.',
        required=True,
    )
    type = properties.StringChoice(
        'The type of workflow.',
        choices=['automatic', 'manual'],
        default='manual',
        required=True,
    )
    status = properties.StringChoice(
        'The status of the workflow.',
        choices=['active', 'inactive', 'invalid'],
        default='invalid',
        required=True,
    )
    order = properties.Integer(
        'The order of the workflow.',
        default=1,
        required=True,
    )
    name = properties.String(
        'Workflow name.',
        required=True,
    )
    created_at = properties.DateTime(
        'UTC time when this workflow was created.', )
    modified_at = properties.DateTime(
        'UTC time when this workflow was modified.', )
Beispiel #2
0
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'
Beispiel #3
0
    def test_datetime(self):

        class DateTimeOpts(properties.HasProperties):
            mydate = properties.DateTime('my date')

        dttm = DateTimeOpts()

        with self.assertRaises(ValueError):
            dttm.mydate = 2010
        with self.assertRaises(ValueError):
            dttm.mydate = '2010'
        dttm.mydate = datetime.datetime(2010, 1, 2)
        dttm.mydate = '2010-01-02'
        assert dttm.mydate == datetime.datetime(2010, 1, 2)
        dttm.mydate = '2010/01/02'
        assert dttm.mydate == datetime.datetime(2010, 1, 2)
        dttm.mydate = '2010-01-02T00:00:00Z'
        assert dttm.mydate == datetime.datetime(2010, 1, 2)

        assert properties.DateTime.to_json(dttm.mydate) == '2010-01-02T00:00:00Z'

        self.assertEqual(dttm.serialize(include_class=False),
                         {'mydate': '2010-01-02T00:00:00Z'})
        assert DateTimeOpts.deserialize(
            {'mydate': '2010-01-02'}
        ).mydate == datetime.datetime(2010, 1, 2)

        assert properties.DateTime('').equal(datetime.datetime(2010, 1, 2),
                                             datetime.datetime(2010, 1, 2))
        assert not properties.DateTime('').equal(datetime.datetime(2010, 1, 2),
                                                 datetime.datetime(2010, 1, 3))
Beispiel #4
0
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.', )
Beispiel #5
0
class Rating(BaseModel):

    customer = properties.Instance(
        'Partial customer object.',
        instance_class=Customer,
        required=True,
    )
    ticket_id = properties.Integer(
        'Ticket ID',
        required=True,
    )
    thread_id = properties.Integer(
        'Thread ID',
        required=True,
    )
    mailbox = properties.Instance(
        'Reference to the mailbox that the conversation belongs to.',
        instance_class=MailboxRef,
        required=True,
    )
    rating = properties.StringChoice(
        'Satisfaction rating.',
        choices=['Great', 'Okay', 'Bad'],
        required=True,
    )
    comments = properties.String('Additional comments', )
    created_at = properties.DateTime(
        'UTC time when this rating was created.', )
    modified_at = properties.DateTime(
        'UTC time when this rating was modified.', )
Beispiel #6
0
class DomainConditionDateTime(DomainCondition):
    """This represents a date time query."""

    value = properties.DateTime(
        'Date From',
        required=True,
    )
    value_to = properties.DateTime('Date To', )

    def __init__(self, field, value_from, value_to=None):
        """Initialize a new datetime query condition.

        Args:
            field (str): Field name to search on. This should be the
                Pythonified name as in the internal models, not the
                name as provided in the API e.g. ``first_name`` for
                the Customer's first name instead of ``firstName``.
            value_from (date or datetime): The start value of the field.
            value_to (date or datetime, optional): The ending value for
                the field. If omitted, will search to now.
        """
        return super(DomainConditionDateTime, self).__init__(
            field=field,
            value=value_from,
            value_to=value_to,
        )

    def __str__(self):
        """Return a string usable as a query part in an API request."""
        value_to = self.value_to.isoformat() if self.value_to else '*'
        return '%s:[%sZ TO %sZ]' % (
            self.field_name,
            self.value.isoformat(),
            value_to,
        )
Beispiel #7
0
class DateTimeArray(ScalarArray):
    """Shared array of DateTimes"""
    array = properties.List(
        'Shared array of DateTimes',
        prop=properties.DateTime(''),
        default=list,
    )
Beispiel #8
0
class Folder(BaseModel):

    name = properties.String(
        'Folder name',
        required=True,
    )
    type = properties.StringChoice(
        'The type of folder.',
        choices=[
            'needsattention',
            'drafts',
            'assigned',
            'open',
            'closed',
            'spam',
            'mine',
            'team',
        ],
        default='drafts',
        required=True,
    )
    user_id = properties.Integer(
        'If the folder type is ``MyTickets``, this represents the Help Scout '
        'user to which this folder belongs. Otherwise it is empty.', )
    total_count = properties.Integer(
        'Total number of conversations in this folder.', )
    active_count = properties.Integer(
        'Total number of conversations in this folder that are in an active '
        'state (vs pending).', )
    modified_at = properties.DateTime(
        'UTC time when this folder was modified.', )
class BaseConversation(BaseModel):
    """This represents a basic conversation, meant to be subclassed."""

    number = properties.Integer(
        'The conversation number displayed in the UI. This number can be used '
        'in combination with the id to construct a URI to the conversation on '
        'the Help Scout website. Example: '
        '``https://secure.helpscout.net/conversation/<id>/<number>/``',
        required=True,
    )
    subject = properties.String(
        'The subject of the conversation.',
        required=True,
    )
    status = properties.StringChoice(
        'Status of the conversation.',
        choices=['active', 'pending', 'closed', 'spam'],
        default='pending',
        required=True,
    )
    thread_count = properties.Integer(
        'This count represents the number of published threads found on the '
        'conversation (it does not include line items, drafts or threads held '
        'for review by Traffic Cop).',
        required=True,
    )
    preview = properties.String(
        'Conversation preview.',
    )
    modified_at = properties.DateTime(
        'UTC time when a user last modified this conversation.',
    )
Beispiel #10
0
class Mailbox(MailboxRef):

    slug = properties.String(
        'Key used to represent this Mailbox.',
        required=True,
    )
    email = properties.String(
        'Email address',
        required=True,
    )
    folders = properties.List(
        'Folders that this mailbox contains.',
        prop=Folder,
    )
    created_at = properties.DateTime(
        'UTC time when this mailbox was created.', )
    modified_at = properties.DateTime(
        'UTC time when this mailbox was modified.', )
Beispiel #11
0
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,
    )
Beispiel #12
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.',
    )
Beispiel #13
0
class Project(ContentModel):
    """OMF Project for serializing to .omf file"""
    author = properties.String('Author', default='')
    revision = properties.String('Revision', default='')
    date = properties.DateTime('Date associated with the project data',
                               required=False)
    units = properties.String('Spatial units of project', default='')
    elements = properties.List(
        'Project Elements',
        prop=ProjectElement,
        default=list,
    )
    origin = properties.Vector3('Origin point for all elements in the project',
                                default=[0., 0., 0.])
Beispiel #14
0
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'),
    )
    date = properties.DateTime('DateTime')
    color = properties.Color('Color')
    not_a_field = True
Beispiel #15
0
 class DateTimeOpts(properties.HasProperties):
     mydate = properties.DateTime('my date')
class Conversation(BaseConversation):
    """This represents a full conversation result."""

    type = properties.StringChoice(
        'The type of conversation.',
        choices=['email', 'chat', 'phone', 'spam'],
        required=True,
    )
    folder_id = properties.Integer(
        'ID of the Mailbox Folder to which this conversation resides.',
        required=True,
    )
    is_draft = properties.Bool(
        'Is this a draft conversation? This property duplicates ``draft``, '
        'but both are received in API responses at the same time so neither '
        'can be considered "deprecated".', )
    draft = properties.Bool(
        'Is this a draft conversation? This property duplicates '
        '``is_draft``, but both are received in API responses at the same '
        'time so neither can be considered "deprecated".', )
    owner = properties.Instance(
        'The Help Scout user who is currently assigned to this conversation.',
        instance_class=Person,
        required=True,
    )
    mailbox = properties.Instance(
        'The mailbox to which this conversation belongs.',
        instance_class=MailboxRef,
        required=True,
    )
    customer = properties.Instance(
        'The customer who this conversation is associated with.',
        instance_class=Person,
        required=True,
    )
    created_by = properties.Instance(
        'The ``Person`` who created this conversation. The ``type`` property '
        'will specify whether it was created by a ``user`` or a ``customer``.',
        instance_class=Person,
    )
    created_by_type = properties.String(
        'The type of user that created this conversation.', )
    created_at = properties.DateTime(
        'UTC time when this conversation was created.', )
    closed_at = properties.DateTime(
        'UTC time when this conversation was closed. Null if not closed.', )
    closed_by = properties.Instance(
        'The Help Scout user who closed this conversation.',
        instance_class=Person,
    )
    source = properties.Instance(
        'Specifies the method in which this conversation was created.',
        instance_class=Source,
    )
    threads = properties.List(
        'Threads associated with the conversation.',
        prop=Thread,
    )
    cc = properties.List(
        'Emails that are CCd.',
        prop=properties.String('Email Address', ),
    )
    bcc = properties.List(
        'Emails that are BCCd.',
        prop=properties.String('Email Address', ),
    )
    tags = properties.List(
        'Tags for the conversation',
        prop=properties.String('Tag Name'),
    )
    spam = properties.Bool('If this conversation is marked as SPAM.', )
    locked = properties.Bool('If this conversation is locked from editing.')
    user_modified_at = properties.DateTime(
        'Last time that this conversation was edited by a user.', )
Beispiel #17
0
class EarthquakeInterferogram(properties.HasProperties):
    title = properties.String(
        'name of the earthquake',
        required=True
    )

    description = properties.String(
        'description of the event',
        required=False
    )

    location = properties.Vector2(
        'interferogram location (bottom N, left E)',
        required=True
    )

    location_UTM_zone = properties.Integer(
        'UTM zone',
        required=True
    )

    shape = properties.Array(
        'number of pixels in the interferogram',
        shape=(2,),
        dtype=int,
        required=True
    )

    pixel_size = properties.Array(
        'Size of each pixel (northing, easting)',
        shape=(2,),
        dtype=float,
        required=True
    )

    data = properties.Array(
        'Processed interferogram data (unwrapped)',
        dtype=float,
        required=True
    )

    ref = properties.Vector2(
        'interferogram reference',
        required=True
    )

    ref_incidence = properties.Float(
        'Incidence angle',
        required=True
    )

    scaling = properties.Float(
        'Scaling of the interferogram',
        default=1.0
    )

    satellite_name = properties.String('Name of the satelite.')

    satellite_fringe_interval = properties.Float(
        'Fringe interval',
        default=0.028333
    )

    satellite_azimuth = properties.Float(
        'satellite_azimuth',
        required=True
    )

    satellite_altitude = properties.Float(
        'satellite_altitude',
        required=True
    )

    local_rigidity = properties.Float(
        'Local rigidity',
        default=3e10
    )

    local_earth_radius = properties.Float(
        'Earth radius',
        default=6371000.
    )

    date1 = properties.DateTime(
        'date1',
        required=True
    )

    date2 = properties.DateTime(
        'date2',
        required=True
    )

    processed_by = properties.String(
        'processed_by',
        required=True
    )

    processed_date = properties.DateTime(
        'processed_date',
        required=True
    )

    copyright = properties.String(
        'copyright',
        required=True
    )

    data_source = properties.String(
        'data_source',
        required=True
    )

    event_date = properties.DateTime('Date of the earthquake')
    event_gcmt_id = properties.String('GCMT ID')
    event_name = properties.String('Earthquake name')
    event_country = properties.String('Earthquake country')

    def _get_plot_data(self):

        vectorNx = (
            np.r_[
                0,
                np.cumsum(
                    (self.pixel_size[0],) * self.shape[0]
                )
            ] + self.location[0]
        )
        vectorNy = (
            np.r_[
                0,
                np.cumsum(
                    (self.pixel_size[1],) * self.shape[1]
                )
            ] + self.location[1]
        ) - self.pixel_size[1] * self.shape[1]

        data = self.data.copy()
        data = np.flipud(data.reshape(self.shape, order='F').T)
        data[data == 0] = np.nan
        data *= self.scaling

        return vectorNx, vectorNy, data

    def plot_interferogram(self, wrap=True, ax=None):

        self.assert_valid

        if ax is None:
            plt.figure()
            ax = plt.subplot(111)

        vectorNx, vectorNy, data = self._get_plot_data()

        if wrap:
            cmap = plt.cm.hsv
            data = data % self.satellite_fringe_interval
            vmin, vmax = 0.0, self.satellite_fringe_interval
        else:
            cmap = plt.cm.jet
            vmin = np.nanmin(data)
            vmax = np.nanmax(data)

        out = ax.pcolormesh(
            vectorNx,
            vectorNy,
            np.ma.masked_where(np.isnan(data), data),
            vmin=vmin,
            vmax=vmax,
            cmap=cmap
        )

        ax.set_title(self.title)
        ax.axis('equal')
        ax.set_xlabel('Easting, m (UTM Zone {})'.format(
            self.location_UTM_zone
        ))
        ax.set_ylabel('Northing, m')

        cb = plt.colorbar(out, ax=ax)
        cb.set_label('Displacement, m')

        return out

    def plot_mask(self, ax=None, opacity=0.2):

        if ax is None:
            plt.figure()
            ax = plt.subplot(111)

        vectorNx, vectorNy, data = self._get_plot_data()

        from matplotlib import colors
        cmap = colors.ListedColormap([(1, 1, 1, opacity)])

        out = ax.pcolormesh(
            vectorNx,
            vectorNy,
            np.ma.masked_where(~np.isnan(data), data),
            cmap=cmap
        )

        ax.set_title(self.title)
        ax.axis('equal')
        ax.set_xlabel('Easting, m (UTM Zone {})'.format(
            self.location_UTM_zone
        ))
        ax.set_ylabel('Northing, m')

        return out

    def get_LOS_vector(self, locations):
        """
        calculate beta - the angle at earth center between reference point
        and satellite nadir
        """
        if not isinstance(locations, list):
            locations = [locations]

        utmZone = self.location_UTM_zone
        refPoint = vmath.Vector3(self.ref.x, self.ref.y, 0)
        satAltitude = self.satellite_altitude
        satAzimuth = self.satellite_azimuth
        satIncidence = self.ref_incidence
        earthRadius = self.local_earth_radius

        DEG2RAD = np.pi / 180.
        alpha = satIncidence * DEG2RAD
        beta = (earthRadius / (satAltitude + earthRadius)) * np.sin(alpha)
        beta = alpha - np.arcsin(beta)
        beta = beta / DEG2RAD

        # calculate angular separation of (x,y) from satellite track passing
        # through (origx, origy) with azimuth satAzimuth

        # Long lat **NOT** lat long
        origy, origx = utm.to_latlon(
            refPoint.x, refPoint.y, np.abs(utmZone), northern=utmZone > 0
        )

        xy = np.array([
            utm.to_latlon(u[0], u[1], np.abs(utmZone), northern=utmZone > 0)
            for u in locations
        ])
        y = xy[:, 0]
        x = xy[:, 1]

        angdist = self._ang_to_gc(x, y, origx, origy, satAzimuth)

        # calculate beta2, the angle at earth center between roaming point and
        # satellite nadir track, assuming right-looking satellite

        beta2 = beta - angdist
        beta2 = beta2 * DEG2RAD

        # calculate alpha2, the new incidence angle

        alpha2 = np.sin(beta2) / (
            np.cos(beta2) - (earthRadius / (earthRadius + satAltitude))
        )
        alpha2 = np.arctan(alpha2)
        alpha2 = alpha2 / DEG2RAD

        # calculate pointing vector

        satIncidence = 90 - alpha2
        satAzimuth = 360 - satAzimuth

        los_x = -np.cos(satAzimuth * DEG2RAD) * np.cos(satIncidence * DEG2RAD)
        los_y = -np.sin(satAzimuth * DEG2RAD) * np.cos(satIncidence * DEG2RAD)
        los_z = np.sin(satIncidence * DEG2RAD)

        return vmath.Vector3Array([los_x, los_y, los_z])

    @staticmethod
    def _ang_to_gc(x, y, origx, origy, satAzimuth):
        """
        Calculate angular distance to great circle passing through
        given point
        """

        Ngc = np.zeros(3)
        cartxy = np.zeros((len(x), 3))
        satAzimuth = np.deg2rad(satAzimuth)
        origx = np.deg2rad(origx)
        origy = np.deg2rad(origy)

        x = np.deg2rad(x)
        y = np.deg2rad(y)

        # 1. calc geocentric norm vec to great circle, Ngc = Rz*Ry*Rx*[0;1;0]
        #    where Rz = rotation of origx about geocentric z-axis
        #    where Ry = rotation of origy about geocentric y-axis
        #    where Rx = rotation of satAzimuth about geocentric x-axis
        #    and [0;1;0] is geocentric norm vec to N-S Great Circle through 0 0

        Ngc[0] = (
                    (np.sin(satAzimuth) * np.sin(origy) * np.cos(origx)) -
                    (np.cos(satAzimuth) * np.sin(origx))
                 )
        Ngc[1] = (
                    (np.sin(satAzimuth) * np.sin(origy) * np.sin(origx)) +
                    (np.cos(satAzimuth) * np.cos(origx))
                 )
        Ngc[2] = -np.sin(satAzimuth) * np.cos(origy)

        # 2. calculate unit vector geocentric coordinates for lon/lat
        #    position (x,y)

        cartxy[:, 0] = np.cos(x) * np.cos(y)
        cartxy[:, 1] = np.sin(x) * np.cos(y)
        cartxy[:, 2] = np.sin(y)

        # 3. Dot product between Ngc and cartxy gives angle 90 degrees
        #    bigger than what we want

        angdist = (
                        Ngc[0]*cartxy[:, 0] +
                        Ngc[1]*cartxy[:, 1] +
                        Ngc[2]*cartxy[:, 2]
                  )

        angdist = np.rad2deg(np.arccos(angdist)) - 90

        return angdist