General
GET /api/events
Returns a list of events.
The following query string parameters are supported to filter, sort and pagingate the returned list:
| Query String Parameter | Type | Description |
|---|---|---|
filter |
string |
A comma-separated list of filters to limit the results with (see Filtering). See the below table for the list of available filters |
sort |
string |
A comma-separated list of sort criteria (see Sorting). See the below table for the list of available sort criteria |
limit |
integer |
The maximum number of results to return (see Pagination) |
offset |
integer |
The index of the first result to return (see Pagination) |
The following filters are available:
| Filter Name | Description |
|---|---|
contributors |
Events where the contributors match. Can occur multiple times |
location |
Events based upon the location it is scheduled in |
series |
Events based upon which series they are a part of. Use the series identifier here. If using version 1.1.0 or higher, please use is_part_of instead |
subject |
Filters events based upon which subject they are a part of |
textFilter |
Filters events where any part of the event's metadata fields match this value |
identifier |
Filters events whose identifiers match this value. Can occur multiple times (version 1.1.0 and higher) |
title |
Filters events whose title match this value (version 1.1.0 and higher) |
description |
Filters events whose description match this value (version 1.1.0 and higher) |
series_name |
Filters events that belong to series with the given name (version 1.1.0 or higher) |
language |
Filters events whose language match this value (version 1.1.0 or higher) |
created |
Filters events whose created match this value (version 1.1.0 or higher) |
license |
Filters events whose license match this value (version 1.1.0 or higher) |
rightsholder |
Filters events whose rights holder matches this value (version 1.1.0 or higher) |
status |
Filters events based on their status (version 1.1.0 or higher) |
is_part_of |
Events based upon which series they are a part of. Use the series identifier here (version 1.1.0 or higher) |
source |
Filter events whose source match this value (version 1.1.0 or higher) |
agent_id |
Filter events based on the capture agent id (version 1.1.0 or higher) |
start |
Filter events based on start date (version 1.1.0 or higer) |
technical_start |
Filter events based on the technical start date (version 1.1.0 or higher) |
Note:
The filters start
and technical_start
expect the following value:
The list can be sorted by the following criteria:
| Sort Criteria | Description |
|---|---|
title |
By the title of the event |
presenter |
By the presenter of the event |
start_date |
By the start date of the event |
end_date |
By the end date of the event |
review_status |
By whether the event has been reviewed and approved or not [DEPRECATED] |
workflow_state |
By the current processing state of the event. Is it scheduled to be recorded (INSTANTIATED), currently processing (RUNNING), paused waiting for a resource or user paused (PAUSED), cancelled (STOPPED), currently failing (FAILING), already failed (FAILED), or finally SUCCEEDED |
scheduling_status |
By the current scheduling status of the event [DEPRECATED] |
series_name |
By the series name of the event |
location |
By the location (capture agent) that the event will be or has been recorded on |
This request additionally supports the following query string parameters to include additional information directly in the response:
| Query String Parameter | Type | Description |
|---|---|---|
sign |
boolean |
Whether public distribution urls should be signed |
withacl |
boolean |
Whether the acl metadata should be included in the response |
withmetadata |
boolean |
Whether the metadata catalogs should be included in the response |
withpublications |
boolean |
Whether the publication ids and urls should be included in the response |
withscheduling |
boolean |
Whether the scheduling information should be included in the response (version 1.1.0 and higher). |
By setting the optional sign
parameter to true
, the method will pre-sign distribution urls if URL signing is turned
on in Opencast. Remember to consider the maximum validity of signed URLs when caching
this response.
Sample request
https://opencast.example.org/api/events?sort=title:DESC&limit=5&offset=1&filter=location:ca-01
Response
200 (OK)
: A (potentially empty) list of events is returned. The list is represented as JSON array where each element
is a JSON object with the following fields:
| Field | Type | Description |
|---|---|---|
identifier |
string |
The unique identifier of the event |
creator |
string |
The technical creator of this event |
presenter * |
array[string] |
The presenters of this event |
created * |
datetime |
The date and time this event was created |
subjects * |
array[string] |
The subjects of this event |
start * |
datetime |
The bibliographic start date and time of this event |
description * |
string |
The description of this event |
title * |
string |
The title of this event |
processing_state |
string |
The current processing state of this event |
duration |
string |
The bibliographic duration of this event |
archive_version |
string |
The current version of this event |
contributor * |
array[string] |
The contributors of this event |
has_previews |
boolean |
Whether this event can be opened with the video editor |
location * |
string |
The bibliographic location of this event |
publication_status |
array[string] |
The publications available for this event |
language * |
string |
The language of this event (version 1.1.0 and higher) |
rightsholder * |
string |
The rights holder of this event (version 1.1.0 and higher) |
license * |
string |
The license of this event (version 1.1.0 and higher) |
is_part_of * |
string |
The technical identifier of the series this event belongs to (version 1.1.0 and higher) |
series |
string |
The title of the series this event belongs to (version 1.1.0 and higher) |
source * |
string |
The source of this event (version 1.1.0 and higher) |
status |
string |
The technical status of this event (version 1.1.0 and higher) |
* Metadata fields of metadata catalog dublincore/episode
Example
[
{
"identifier": "776d4970-bc2d-45c4-900a-1f80b7990cb8",
"creator": "Opencast Project Administrator",
"presenter": [
"Prof. X",
"Dr. Who"
],
"created": "2018-03-19T16:11:48Z",
"subjects": [
"Mathematics",
"Basics"
],
"start": "2018-03-19T16:11:48Z",
"description": "This lecture is about the very basics",
"title": "Lecture 1 - The Basics",
"processing_state": "SUCCEEDED",
"duration": 0,
"archive_version": 3,
"contributor": [
"Prof. X"
],
"has_previews": true,
"location": "",
"publication_status": [
"internal",
"engage-player",
"api",
"oaipmh-default"
]
},
{
"identifier": "2356d450-b42d-94xd-2a0d-3fa04745c0cb8",
"creator": "Opencast Project Administrator",
"presenter": [
],
"created": "2018-04-20T09:38:42Z",
"subjects": [
"Physics"
],
"start": "2018-04-23T08:00:00Z",
"description": "The forces explained",
"title": "Lecture 8 - Advanced stuff",
"processing_state": "SUCCEEDED",
"duration": 0,
"archive_version": 2,
"contributor": [
],
"has_previews": true,
"location": "",
"publication_status": [
"internal",
"engage-player",
"api",
"oaipmh-default"
]
}
]
POST /api/events
Creates an event by sending metadata, access control list, processing instructions and files in a multipart request.
| Multipart Form Parameters | Type | Description |
|---|---|---|
acl |
acl |
A collection of roles with their possible action |
metadata |
catalogs |
Event metadata as Form param |
presenter |
file |
Presenter movie track |
presentation |
file |
Presentation movie track |
audio |
file |
Audio track |
processing |
string |
Processing instructions task configuration |
scheduling |
string |
Scheduling information (version 1.1.0 and higher) |
Scheduling
| Field | Required | Type | Description |
|---|---|---|---|
agent_id |
Yes | string |
The technical identifier of the capture agent |
start |
Yes | datetime |
The date and time (UTC) when the recording shall start |
end |
Yes* | datetime |
The date and time (UTC) when the recording shall end |
duration |
Yes* | integer |
The duration of the recording in milliseconds |
rrule |
Yes* | rrule |
The recurrence rule used to create multiple scheduled events |
* When creating a single scheduled event, either end
or duration
must be specified. When creating multiple
scheduled events, the fields end
, duration
and rrule
are required
To create a single scheduled event, omit the field rrule
. You can specify the start and end of the recording by
using either the fields start
and end
or the fields start
and duration
.
Please note that specifying both end
and duration
is not valid.
To create multiple scheduled events, the field rrule
is used. This field contains the recurrence rule used to
determine the dates and times the scheduled events shall be created within the time period specified by the fields
start
and end
+ duration
.
Please note that duration
is a mandatory field when creating multiple scheduled events.
Additional Notes
- Both
start
andend
must be specified in UTC
Sample
metadata:
[
{
"flavor": "dublincore/episode",
"fields": [
{
"id": "title",
"value": "Captivating title"
},
{
"id": "subjects",
"value": ["John Clark", "Thiago Melo Costa"]
},
{
"id": "description",
"value": "A great description"
},
{
"id": "startDate",
"value": "2016-06-22"
},
{
"id": "startTime",
"value": "13:30:00Z"
}
]
}
]
processing:
{
"workflow": "schedule-and-upload",
"configuration": {
"flagForCutting": "false",
"flagForReview": "false",
"publishToEngage": "true",
"publishToHarvesting": "true",
"straightToPublishing": "true"
}
}
acl:
[
{
"action": "write",
"role": "ROLE_ADMIN"
},
{
"action": "read",
"role": "ROLE_USER"
}
]
scheduling a single event:
{
"agent_id": "ca24",
"start": "2018-03-27T16:00:00Z",
"end": "2018-03-27T19:00:00Z",
"inputs": ["default"],
}
scheduling multiple events:
{
"agent_id": "ca24",
"start": "2019-05-20T16:00:00Z",
"end": "2019-06-10T19:00:00Z",
"inputs": ["default"],
"rrule":"FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=16;BYMINUTE=0",
"duration":1080000;
}
Response
200 (OK)
: Multiple new events were created (scheduling with rrule
).
201 (CREATED)
: A new event is created and its identifier is returned in the Location
header.
400 (BAD REQUEST)
: The request is invalid or inconsistent.
409 (CONFLICT)
: The event could not be created due to a scheduling conflict. A list of conflicting events is returned.
In case of success, when scheduling multiple events (200):
[
{
"identifier": "e6aeb8df-a852-46cd-8128-b89de696f20e"
},
{
"identifier": "90e93bf6-ed95-483b-8e57-3e2de77a786f"
}
]
In case of success (201):
Location: http://api.opencast.org/api/events/e6aeb8df-a852-46cd-8128-b89de696f20e
{
"identifier": "e6aeb8df-a852-46cd-8128-b89de696f20e"
}
In case of a conflict (409):
[
{
"start":"2018-03-21T14:00:00Z",
"end":"2018-03-21T16:00:00Z",
"title":"My Event 06"
}
]
GET /api/events/{event_id}
Returns a single event.
By setting the optional sign
parameter to true
, the method will pre-sign distribution urls if signing is turned on
in Opencast. Remember to consider the maximum validity of signed URLs when caching this
response.
| Query String Parameter | Type | Description |
|---|---|---|
sign |
boolean |
Whether public distribution urls should be signed. |
withacl |
boolean |
Whether the acl metadata should be included in the response. |
withmetadata |
boolean |
Whether the metadata catalogs should be included in the response. |
withpublications |
boolean |
Whether the publication ids and urls should be included in the response. |
withscheduling |
boolean |
Whether the scheduling information should be included in the response (version 1.1.0 and higher). |
Response
200 (OK)
: The event is returned as JSON object with the following fields:
| Field | Type | Description |
|---|---|---|
identifier |
string |
The unique identifier of the event |
creator |
string |
The technical creator of this event |
presenter * |
array[string] |
The presenters of this event |
created * |
datetime |
The date and time this event was created |
subjects * |
array[string] |
The subjects of this event |
start |
datetime |
The technical start date and time of this event |
description * |
string |
The description of this event |
title * |
string |
The title of this event |
processing_state |
string |
The current processing state of this event |
duration |
string |
The bibliographic duration of this event |
archive_version |
string |
The current version of this event |
contributor * |
array[string] |
The contributors of this event |
has_previews |
boolean |
Whether this event can be opened with the video editor |
location * |
string |
The bibliographic location of this event |
publication_status |
array[string] |
The publications available for this event |
language * |
string |
The language of this event (version 1.1.0 and higher) |
rightsholder * |
string |
The rights holder of this event (version 1.1.0 and higher) |
license * |
string |
The license of this event (version 1.1.0 and higher) |
is_part_of * |
string |
The technical identifier of the series this event belongs to (version 1.1.0 and higher) |
series |
string |
The title of the series this event belongs to (version 1.1.0 and higher) |
source * |
string |
The source of this event (version 1.1.0 and higher) |
status |
string |
The technical status of this event (version 1.1.0 and higher) |
* Metadata fields of metadata catalog dublincore/episode
404 (NOT FOUND)
: The specified event does not exist.
{
"identifier": "776d4970-bc2d-45c4-900a-1f80b7990cb8",
"creator": "Opencast Project Administrator",
"presenter": [
"Prof. X",
"Dr. Who"
],
"created": "2018-03-19T16:11:48Z",
"subjects": [
"Mathematics",
"Basics"
],
"start": "2018-03-19T16:11:48Z",
"description": "This lecture is about the very basics",
"title": "Lecture 1 - The Basics",
"processing_state": "SUCCEEDED",
"duration": 0,
"archive_version": 3,
"contributor": [
"Prof. X"
],
"has_previews": true,
"location": "",
"publication_status": [
"internal",
"engage-player",
"api",
"oaipmh-default"
]
}
POST /api/events/{event_id}
Updates an event.
| Multipart Form Parameters | Type | Description |
|---|---|---|
acl |
acl |
A collection of roles with their possible action |
metadata |
catalogs |
Event metadata as Form param |
presenter |
file |
Presenter movie track |
presentation |
file |
Presentation movie track |
audio |
file |
Audio track |
processing |
string |
Processing instructions task configuration |
scheduling |
string |
Scheduling information (version 1.1.0 and higher) |
Sample
This sample request will update the Dublin Core metadata section of the event only.
metadata:
[
{
"flavor": "dublincore/episode",
"fields": [
{
"id": "title",
"value": "Captivating title"
},
{
"id": "subjects",
"value": ["Space", "Final Frontier"]
},
{
"id": "description",
"value": "A great description"
}
]
}
]
Response
204 (NO CONTENT)
: The event has been updated.
404 (NOT FOUND)
: The specified event does not exist.
409 (CONFLICT)
: The event could not be updated due to a scheduling conflict. A list of conflicting events is returned.
In case of a conflict (when updating scheduling
):
[
{
"start":"2018-03-21T14:00:00Z",
"end":"2018-03-21T16:00:00Z",
"title":"My Event 06"
}
]
DELETE /api/events/{event_id}
Deletes an event.
Response
204 (NO CONTENT)
: The event has been deleted.
404 (NOT FOUND)
: The specified event does not exist.
Access Policy
Most events in Opencast come with an access control list (ACL), containing entries that map actions to roles, either allowing or denying that action.
The section on roles in the chapter on Authorization will help shed some light on what kind of roles are available and how they are assigned to the current user.
For more information about access control lists, please refer to Access Control Lists.
GET /api/events/{event_id}/acl
Returns an event's access policy.
Response
200 (OK)
: The access control list for the specified event is returned as acl
.
404 (NOT FOUND)
: The specified event does not exist.
[
{
"allow": true,
"action": "write",
"role": "ROLE_ADMIN"
},
{
"allow": true,
"action": "read",
"role": "ROLE_USER"
}
]
PUT /api/events/{event_id}/acl
Update an event's access policy.
| Form Parameters | Type | Description |
|---|---|---|
acl |
acl |
Access policy |
Note that the existing access control list will be overwritten.
Sample
acl:
[
{
"allow": true,
"action": "write",
"role": "ROLE_ADMIN"
},
{
"allow": true,
"action": "read",
"role": "ROLE_USER"
}
]
Response
204 (NO CONTENT)
: The access control list for the specified event is updated.
404 (NOT FOUND)
: The specified event does not exist.
POST /api/events/{event_id}/acl/{action}
Grants permission to execute action
on the specified event to any user with role role
. Note that this is a
convenience method to avoid having to build and post a complete access control list.
| Path Parameters | Type | Description |
|---|---|---|
event_id |
string |
Event identifier |
action |
string |
The action that is allowed to be executed |
| Form Parameters | Type | Description |
|---|---|---|
role |
string |
The role that is granted permission |
Note that other access control lists entries will not be affected by this request.
Sample
role: "ROLE_STUDENT"
Response
204 (NO CONTENT)
: The permission has been created in the access control list of the specified event.
404 (NOT FOUND)
: The specified event does not exist.
DELETE /api/events/{event_id}/acl/{action}/{role}
Revokes permission to execute action
on the specified event from any user with role role
.
| Path Parameters | Type | Description |
|---|---|---|
event_id |
string |
Event identifier |
action |
string |
The action that is no longer allowed to be executed |
role |
string |
The role that is no longer granted permission |
Note that other access control lists entries will not be affected by this request.
Response
204 (NO CONTENT)
: The permission has been revoked from the access control list of the specified event.
404 (NOT FOUND)
: The specified event does not exist.
Metadata
This section describes how to use the External API to work with metadata catalogs associated to events.
Opencast manages the bibliographic metadata of series using metadata catalogs which are identified by flavors.
The default metadata catalog for Opencast events has the flavor dublincore/episode
. Opencast additionally supports
extended metadata catalogs for series that can be configured.
The External API supports both the default event metadata catalog and events extended metadata catalogs. For the default event metadata catalog, the metadata is directly returned in the responses.
Since the metadata catalogs can be configured, the External API provides a facility to retrieve the catalog configuration of series metadata catalogs. For more details about this mechanism, please refer to "Metadata Catalogs".
GET /api/events/{event_id}/metadata
Returns the complete set of metadata.
Response
200 (OK)
: The metadata collection is returned as catalogs
.
404 (OK)
: The specified event does not exist.
[
{
"label": "EVENTS.EVENTS.DETAILS.CATALOG.EPISODE",
"flavor": "dublincore/episode",
"fields": [
{
"id": "title",
"readOnly": false,
"value": "Captivating title",
"label": "EVENTS.EVENTS.DETAILS.METADATA.TITLE",
"type": "text",
"required": true
},
{
"id": "description",
"readOnly": false,
"value": "A great description",
"label": "EVENTS.EVENTS.DETAILS.METADATA.DESCRIPTION",
"type": "text_long",
"required": false
}
]
},
{
"label": "EVENTS.EVENTS.DETAILS.CATALOG.LICENSE",
"flavor": "license/episode",
"fields": [
{
"id": "license",
"readOnly": false,
"value": "CCND",
"label": "EVENTS.EVENTS.DETAILS.METADATA.LICENSE",
"collection": {
"BSD": "EVENTS.LICENSE.BSD",
"GPL3": "EVENTS.LICENSE.GPL",
"CCND": "EVENTS.LICENSE.CCND"
},
"type": "text",
"required": false
}
]
}
]
GET /api/events/{event_id}/metadata
Returns the event's metadata of the specified type. For a metadata catalog there is the flavor such as
dublincore/episode
and this is the unique type.
| Query String Parameters | Type | Description |
|---|---|---|
type |
flavor |
The type of metadata to get |
Response
200 (OK)
: The metadata collection is returned as fields
.
404 (NOT FOUND)
: The specified event does not exist.
[
{
"id": "title",
"readOnly": false,
"value": "Captivating title",
"label": "EVENTS.EVENTS.DETAILS.METADATA.TITLE",
"type": "text",
"required": true
},
{
"id": "description",
"readOnly": false,
"value": "A great description",
"label": "EVENTS.EVENTS.DETAILS.METADATA.DESCRIPTION",
"type": "text_long",
"required": false
}
]
PUT /api/events/{event_id}/metadata
Update the metadata with the matching type of the specified event. For a metadata catalog there is the flavor such as
dublincore/episode
and this is the unique type.
| Query String Parameters | Type | Description |
|---|---|---|
type |
flavor |
The type of metadata to update |
| Form Parameters | Type | Description |
|---|---|---|
metadata |
values |
Metadata fields and values to be updated |
Note that metadata fields not included in the form parameter metadata
will not be updated.
Sample
metadata:
[
{
"id": "title",
"value": "Captivating title"
},
{
"id": "subjects",
"value": ["Space", "Final Frontier"]
},
{
"id": "description",
"value": "A great description"
}
]
Response
204 (NO CONTENT)
: The metadata of the given namespace has been updated.
400 (BAD REQUEST)
: The request is invalid or inconsistent.
404 (NOT FOUND)
: The specified event does not exist.
DELETE /api/events/{event_id}/metadata
Delete the metadata namespace catalog of the specified event. This will remove all fields and values of the catalog.
| Query String Parameters | Type | Description |
|---|---|---|
type |
flavor |
The type of metadata to delete |
Note that the metadata catalog of type dublincore/episode
cannot be deleted.
Response
204 (NO CONTENT)
: The metadata of the given namespace has been updated.
403 (FORBIDDEN)
: The main metadata catalog dublincore/episode cannot be deleted as it has mandatory fields.
404 (NOT FOUND)
: The specified event does not exist.
Publications
GET /api/events/{event_id}/publications
Returns an event's list of publications.
| Query String Parameter | Type | Description |
|---|---|---|
sign |
boolean |
Whether public distribution urls should be signed |
Response
200 (OK)
: The list of publications is returned.
404 (NOT FOUND)
: The specified event does not exist.
[
{
"id":"publication-1",
"channel":"engage",
"mediatype":"text/html",
"url":"http://engage.opencast.org/engage/ui/player.html?id=123"
},
{
"id":"publication-2",
"channel":"oaipmh",
"mediatype":"text/html",
"url":"http://oaipmh.opencast.org/default/?verb=GetRecord&id=123"
}
]
GET /api/events/{event_id}/publications/{publication_id}
Returns a single publication.
| Query String Parameter | Type | Description |
|---|---|---|
sign |
boolean |
Whether public distribution urls should be signed |
Response
200 (OK)
: The track details are returned.
404 (NOT FOUND)
: The specified event does not exist.
404 (NOT FOUND)
: The specified publication does not exist.
{
"id":"publication-1",
"channel":"engage",
"mediatype":"text/html",
"url":"http://engage.opencast.org/engage/ui/player.html?id=123",
"media":[
{
"id":"track-1",
"mediatype":"video/mp4",
"url":"http://download.opencast.org/123/presenter.mp4",
"flavor":"presenter/delivery",
"size":84938490,
"checksum":"58308405383094",
"tags":[
],
"has_audio":true,
"has_video":true,
"duration":3648,
"description":"Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 640x360, 447 kb/s, 25 fps, 25"
},
{
"id":"track-2",
"mediatype":"audio/aac",
"url":"http://download.opencast.org/123/presenter.m4a",
"flavor":"presenter/audio",
"size":9364,
"checksum":"839478372",
"tags":[
],
"has_audio":true,
"has_video":false,
"duration":3648,
"description":"aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 96 kb/s (default)"
}
],
"attachments":[
{
"id":"attachment-1",
"mediatype":"image/png",
"url":"http://download.opencast.org/123/preview.png",
"flavor":"presenter/preview",
"size":62728,
"checksum":"389475737",
"tags":[
]
}
],
"metadata":[
{
"id":"catalog-1",
"mediatype":"text/xml",
"url":"http://download.opencast.org/123/dublincore.xml",
"flavor":"dublincore/episode",
"size":364,
"checksum":"18498498383",
"tags":[
]
}
]
}
Scheduling Information
GET /api/events/{event_id}/scheduling
Available since API version 1.1.0.
Returns an event's scheduling information.
Response
200 (OK)
: The scheduling information is returned.
204 (NO CONTENT)
: The event is not scheduled.
404 (NOT FOUND)
: The specified event does not exist.
{
"agent_id": "ca24",
"start": "2018-03-27T16:00:00Z",
"end": "2018-03-27T19:00:00Z",
"inputs": ["default"]
}
PUT /api/events/{event_id}/scheduling
Available since API version 1.1.0.
Update the scheduling information of the event with id {event_id}
.
| Form Parameters | Type | Description | Default | Version |
|---|---|---|---|---|
scheduling |
string |
The scheduling information. | Required | 1.1.0 |
allowConflict |
boolean |
Allow conflicts when updating scheduling. | false | 1.2.0 |
Sample
scheduling:
{
"agent_id": "ca24",
"start": "2018-03-27T16:00:00Z",
"end": "2018-03-27T19:00:00Z",
"inputs": ["default"]
}
Response
204 (NO CONTENT)
: The scheduling information of the event has been updated.
400 (BAD REQUEST)
: The request is invalid or inconsistent.
404 (NOT FOUND)
: The specified event does not exist.
409 (CONFLICT)
: The scheduling information could not be updated due to a conflict. A list of conflicting events is returned.
In case of a conflict:
[
{
"start":"2018-03-21T14:00:00Z",
"end":"2018-03-21T16:00:00Z",
"title":"My Event 06"
}
]
allowConflict
allows the schedule to be updated without checking for conflicts.
To allow conflicts (true
) the call MUST be made with a user that has an Administrative Role.
If not handled properly this will likely cause two or more events to be scheduled on a particular capture agent at the same time, which will then cause a capture failure for all but one of the events.
The person making this call and allowing conflicts to exist, will bear the responsibility of resolving the conflicts that might result.


|
|
|
|
Hello {$member.firstname},
We are sorry to say your membership is ending!
There may have been problem with the credit card we have on file.
Please contact us to update your information:
by phone:<PHONE_NUMBER> By email at<EMAIL_ADDRESS>With exclusive Str8UpGayPornMovies Originals content you won't find anywhere else, plus new updates every day, from studios like Falcon, Raging Stallion, Treasure Island, and hundreds of other super hot studios, there's never been a better time to stick with Str8UpGayPornMovies.
To reactivate your membership go to
Str8UpGayPornMovies.com.
If you don't do anything your membership will expire on{if $member.expires} {$member.expires|date_format:"%m-%d-%Y"} {else} {$member.nats_expires|date_format:"%m-%d-%Y"}{/if}.
Thanks for being a part of Str8UpGayPornMovies and we hope you come back soon.
Sincerely,
Everyone at Str8UpGayPornMovies
Str8UpGayPornMovies.com.
|
|
|


litelist v0.0.1 Litelist.Scheduler
Defines a quantum Scheduler.
When used, the quantum scheduler expects the :otp_app
as option.
The :otp_app
should point to an OTP application that has
the quantum runner configuration. For example, the quantum scheduler:
defmodule Litelist.Scheduler do
use Quantum.Scheduler, otp_app: litelist
end
Could be configured with:
config litelist, Litelist.Scheduler,
jobs: [
{"@daily", {Backup, :backup, []},
]
Configuration:
:timeout
- Sometimes, you may come across GenServer timeout errors esp. when you have too many jobs or high load. The default GenServer.call timeout is 5000.:jobs
- list of cron jobs to execute:global
- When you have a cluster of nodes, you may not want same jobs to be generated on every single node, e.g. jobs involving db changes.In this case, you may choose to run Quantum as a global process, thus preventing same job being run multiple times because of it being generated on multiple nodes. With the following configuration, Quantum will be run as a globally unique process across the cluster.
:schedule
- Default schedule of new Job:run_strategy
- Default Run Strategy of new Job:overlap
- Default overlap of new Job,:timezone
- Default timezone of new Job
Link to this section Summary
Functions
Activates a job by name
Adds a new job
Returns the configuration stored in the :otp_app
environment
Deactivates a job by name
Deletes all jobs
Deletes a job by name
Resolves a job by name
Returns the list of currently defined jobs
Creates a new Job. The job can be added by calling add_job/1
Starts supervision and return {:ok, pid}
or just :ok
if nothing needs to be done
Shuts down the quantum represented by the given pid
Link to this section Functions
Activates a job by name
Callback implementation for Quantum.Scheduler.activate_job/2
.
Adds a new job
Callback implementation for Quantum.Scheduler.add_job/2
.
Returns the configuration stored in the :otp_app
environment.
Callback implementation for Quantum.Scheduler.config/1
.
Deactivates a job by name
Callback implementation for Quantum.Scheduler.deactivate_job/2
.
Deletes all jobs
Callback implementation for Quantum.Scheduler.delete_all_jobs/1
.
Deletes a job by name
Callback implementation for Quantum.Scheduler.delete_job/2
.
Resolves a job by name
Callback implementation for Quantum.Scheduler.find_job/2
.
Returns the list of currently defined jobs
Callback implementation for Quantum.Scheduler.jobs/1
.
Creates a new Job. The job can be added by calling add_job/1
.
Callback implementation for Quantum.Scheduler.new_job/1
.
Starts supervision and return {:ok, pid}
or just :ok
if nothing needs to be done.
Returns {:error, {:already_started, pid}}
if the repo is already
started or {:error, term}
in case anything else goes wrong.
Options
See the configuration in the moduledoc for options.
Callback implementation for Quantum.Scheduler.start_link/1
.
Shuts down the quantum represented by the given pid.
Callback implementation for Quantum.Scheduler.stop/2
.


A Guide For New Developers
Get StartedTraining to become a full-stack developer will be great news for your career in the long run.
You could have a diverse and rewarding career that follows any number of different paths –it’s up to you to determine which way it goes. There are also multiple routes to get there, and how you train and gain experience is the most important decision you need to make in the short term.
In this e-book we’ll walk you through:
Part One
If you're still not sure whether web development is for you, press the down arrow and we'll explain what a career in web development looks like. If you're already convinced, spin on and press right!
Now is a great time to learn to code:
Another great reason to choose a career in code is that the roles, and the people working in them, are really diverse – there is every opportunity to specialise in an area that excites you, and along the way you’ll work alongside lots of interesting people.
Training and working in tech is definitely not easy, so you’ll need to be resilient and committed to succeed. And technical skills, it goes without saying, are a must.
That said, just knowing how to code will only get you so far – your ability to communicate and collaborate with other people across different disciplines (depending the organisation you work for, and the project you’re involved in) will help you excel.
So a combination of technical competence, people skills and an ability to continuously learn could make the difference between a good career and a great one.
These days, there’s not really any typical route into code. Although many of the students here at We Got Coders have some sort of IT background, we’ve also trained linguists, archaeologists, pilots, lawyers, cheese mongers, musicians, architects... you name it!
Did you know how many jobs there are in tech? Thousands. If you want, being trained in code can take you miles away from the traditional roles in web and mobile app development. You could be exploring:
There are three core types of development:
Ultimately many developers are working towards becoming “full stack” – i.e. they can manage every layer of back-end and front-end technologies, with databases, PHP, HTML, CSS, JavaScript and everything in between.
It’s important to cover all the basics of both front-end and back-end as you learn to code though. Firstly, you’ll get a better understanding of how it all works and where you want to specialize – and secondly, most companies aren’t in a rush to recruit junior front-end developers.
Part Two
Alright, so by now you can see the benefits of learning to code. How can we help? This section is all about We Got Coders and our course offerings. If you'd like find out more, press down; if you'd like to hear from the coders who have completed the course, press right!
We Got Coders is a different kind of code bootcamp. We’re a creative community of coders, sharing skills via an intensive, live-in training programme that’s focused on kickstarting your career in web development.
When it comes to learning, we don't follow the rules. Our unique approach combines a full-time, intensive, bootcamp-style course with mentored work experience placements, fast tracking you into an actual web developer job.
We believe in learning like developers do; so we pair program, write tests before we code and are rigourous about best practices in peer-reviewed code. Get a level of support and feedback like you were being supported into a new web developer role, when you need it.
For those who can't attend our intensive courses, we offer guided learning online to help you whether you are currently in-role already or cannot commit to a course.
We've setup an unparalled creative space surrounded by nature, whilst staying on the outskirts of London. Our Grade II listed manor house training center doubles as a luxury guesthouse, allowing our trainees to learn round the clock and still enjoy all the home comforts.
Overlooking the Lee Valley, the house has 2 classroom facilities, 5 star accommodation, and allows us to deliver intensive courses and workshops simultaneously in a stress-free environment.
Our resident trainees will live the dream whilst they are learning to code, with an on-site chef, steam room, arcade machine, snooker table and home cinema.
Escape the stress of the city and the distractions of commuting – you’ll live and breathe code with your trainers and colleagues, and we’ll take care of everything else.
You’ll avoid burnout and learn more in the peace and quiet of our riverside mansion. Yet it’s still less than an hour away from London.
You’ll live in a creative environment with people from many different backgrounds, and you’ll get constant facetime with your trainer, meaning you can progress faster.
We’ll mentor you as you gain hands-on client experience, putting your new code skills to work on live client projects. And you’ll earn at least £22,000 pro rata for it.
Our course is broken down into stages. Either spend twelve weeks taking back-to-back courses, or take it at your own pace with a combination of online learning and in-person workshops.
Duration: 6 weeks intensive
Learn the building blocks of the web. We cover the principles behind full-stack applications so that you're ready to specialise in modern, full-stack web development.
On this course we'll put the foundations in place to understand any web-based tech stack:
We'll examine various Ruby MVC frameworks and understand how they are built; so rather than working like magic you'll know how the constituent parts fit together.
Duration: 6 weeks intensive
Want to work in a startup? Join the happiest and highest-earning web developers though application of extreme programming and agile techniques.
On this course you'll learn how to apply industry best practices to rapidly prototype web applications for customers:
Duration: 6 weeks intensive
Join the new wave of mobile developers harnessing the power of the web to build their mobile apps. Create slick native applications with a cross-platform approach at the cutting edge of web development.
On this course you'll learn how to deliver compelling mobile applications to customers:
All the courses in the world would be for nothing if there wasn't a solid paying job to go to. We've fixed that. Our 12 week Web Developer Fast Track programme provides a paid work experience placement for developers who have completed our Web Fundamentals course and a specialism of their choosing.
Earn while you learn and get paid £22,000 pro rata for three months. It's essential to put your skills into practice as soon as possible after finishing your course and our client list is a perfect place to start.
Working alongside a senior developer, you will be mentored in the role to ensure that you continue to learn, and that you are delivering value to the client.
Have you graduated within the last two years? Our free training course is perfect for graduates stuck in the catch-22 of not having work experience following their University course.
We bridge the gap between the expectations of a competitive jobs market and your degree course to ensure that you can be well ahead of the pack.
Stay two years in role with us and we will provide your training free of charge.
Next, some of the alumni who have been through the process give their insights into their journey to becoming a web developer.
Part Three
Don't take our word for it! Hear from some of our alumni who have taken the course and see for yourself
The teaching I received at We Got Coders was excellent. I massively endorse the way they go about it; not just teaching about how to achieve the end result, but also what's going on behind the scenes.
For example when they taught us ActiveRecord, instead of just showing us how to use it, we first learnt about database design. Then, we learnt how to speak to it in SQL. Then, we learnt how ActiveRecord does all this for you. Only then did we learn how to use ActiveRecord, giving us a solid understanding that allowed us to master the basics.
We Got Coders isn't just a course that makes you a developer, it's the first step to being a great one.
This course was really fantastic. As a female in my late 30s, I wasn't keen on a frat-house environment. And given my learning style, I respond best to small classes and personalised tuition. I wasn't disappointed on either front. The mansion is beautiful and quiet and our chef created delicious meals. It meant that we were able to wholly focus on consuming the large amount of course work. Most days I was doing 12 - 14 hours coding and loving it!
The instructors clearly cared about our progress and were determined to show us how to be exceptional developers. They made themselves available when I needed help, even if that meant evenings and weekends.
For someone who was basically a beginner coder when I started, I found this a safe and positive learning environment. It's so satisfying to know that I can now confidently create well tested, well written code.
When I arrived at We Got Coders I had a lot of doubts about my abilities and lack of experience. Over the next few weeks they quickly disappeared. It’s a very intensive course, but the instructors made sure that nobody got left behind, making themselves available in the evenings and at weekends.
At the end of the course students have two weeks to build an app of their own choosing from scratch, and present it for select group of industry professionals. I ended up getting hired on the spot and sent straight into a development job in London.
I would highly recommend this course to anyone who's serious about becoming a web developer. The accommodation is amazing, how often do you get to live in a country mansion with a professional chef cooking for you? The 3 month mentoring phase that comes after the course, is really valuable and not something that many other places offer.
Dan has a passion for web development and teaching. He is very knowledgeable and has good communication skills. This makes him a great teacher able to explain in a concise and clear way the most complex concepts. Dan is hard-working and sets high expectations during the web development course which are greatly achieved thanks to his guidance. I definitely recommend Dan because he provides you with the tools you need to successfully become a Full Stack Web Developer and be ready for the job market.
It's time to get coding! We will give you some insights into the process of learning to code and some practical advice to get started
Part Four
So you know that you want to get into web development, and you've seen our courses... but now what? Here is some practical advice on how to get started, get setup and some of the pitfalls you might meet along the way.
Go on, take a wild guess!
5.times { puts "I'm going to learn to code!" }
Press down for the answer!
I'm going to learn to code!
I'm going to learn to code!
I'm going to learn to code!
I'm going to learn to code!
I'm going to learn to code!
That was Ruby, one of the languages that you'll pickup on our course. You can take our Introduction to Ruby programming online from our website, for free.
Alright, so coding isn't always that easy. In fact, learning to code can be very difficult and testing, especially at the start. You'll be eager to build all of those amazing applications, games and business ideas; but you'll need to learn to walk before you can run.
In many ways, learning to code will be similar to how you learned to walk and how to talk. There was a lot of trial and error; but we learned to pick ourselves up and try again. If you can be humble and perservering, then you'll have no problems learning to code in the long run.
The main thing is to not berate yourself if things go wrong. That's normal! Seasoned web developers are used to problems with their coding and know how to deal with failure: treat it as part of the learning process. It's a process that never truly finishes; which is another reason why programming is ultimately so rewarding.
 This is a great way to focus on learning to code rather than battling issues with your environment.
Try one of these tutorials in your coffee break. If you find them interesting, challenging and fun then that's a good sign that coding is indeed for you.
When you're done with that, it's time to take things to the next level...
If you're serious about learning to code, you will need to get your hands on some kit and install the following software programs. If you join one of our courses, we will make time for an installation event before it starts to assist with any problems, but as a basic minimum we would expect the following or the nearest equivalent:
You will need to provide a laptop computer running a UNIX-based operating system, such as Mac OSX or Linux. Windows machines will not be accepted. Limited technical support is provided throughout the course, but you are expected to maintain a stable programming environment. A minimal specification for a laptop would have 2G of RAM, ideally a two-core machine at least. You will need to ensure that you have sufficient disk space.
In practice, developers are not God-like geniuses with an encyclopedic memory. They know when and where to ask for help and learning how to rapidly and accurately lookup information is a very important skill. Learn how to use the Internet like a textbook and usually you'll find the information you need in one or two clicks.
Here are some ideas of places to get started:
What are you waiting for? Now you're all setup and ready to go, we've got a range of offerings to suit everyone.
Take route one to becoming a top web developer. Take a look at our immersive courses and workshops and apply now!


| delete {fs} | R Documentation |
file_delete()
and link_delete()
delete file and links. Compared to
file.remove they always fail if they cannot delete the object rather than
changing return value or signalling a warning. If any inputs are
directories, they are passed to dir_delete()
, so file_delete()
can
therefore be used to delete any filesystem object.
dir_delete()
will first delete the contents of the directory, then remove
the directory. Compared to unlink it will always throw an error if the
directory cannot be deleted rather than being silent or signalling a warning.
file_delete(path) dir_delete(path) link_delete(path)
path |
A character vector of one or more paths. |
The deleted paths (invisibly).
# create a directory, with some files and a link to it dir_create("dir") files <- file_create(path("dir", letters[1:5])) link <- link_create(path_abs("dir"), "link") # All files created dir_exists("dir") file_exists(files) link_exists("link") file_exists(link_path("link")) # Delete a file file_delete(files[1]) file_exists(files[1]) # Delete the directory (which deletes the files as well) dir_delete("dir") file_exists(files) dir_exists("dir") # The link still exists, but what it points to does not. link_exists("link") dir_exists(link_path("link")) # Delete the link link_delete("link") link_exists("link")


2:15
Mike Doe
I would like to meet you to discuss the latest news about
the arrival of the new theme. They say it is going to be one the
best themes on the market
5:15
Alexander Pierce
I would like to meet you to discuss the latest news about
the arrival of the new theme. They say it is going to be one the
best themes on the market
5:30
Susan Doe
I would like to meet you to discuss the latest news about
the arrival of the new theme. They say it is going to be one the
best themes on the market
5:15
Alexander Pierce
I would like to meet you to discuss the latest news about
the arrival of the new theme. They say it is going to be one the
best themes on the market


| Question Pool ID | Question Pool Name | Description | Account Created | Created Date | Parent Pool | Action |
|---|---|---|---|---|---|---|
| {{questionpool.Id}} | {{questionpool.Name}} | {{questionpool.Description}} | {{questionpool.AccountId}} | {{questionpool.CreatedDate | date:'dd/MM/yyyy'}} | {{questionpool.ParentPoolId}} |


See the proposed units for the Creative Commons Core Certification, and send us any OERs, resources, or possible activities that might be used to demonstrate proficiency in the unit topics.
Use the Google form below to suggest resources (or visit directly).
If you have a lot to share, try adding our bookmarklet tool to your browser bar. While visiting any possible resource, just highlight a sentence of text as a description, click the tool, and it will pre-populate the form with the title, URL, and description.
Just drag the button link to your bookmarks bar.


I have always had a sincere passion for finance, the economy and global markets. Understanding how impactful it is to everybody, I've always felt it was an important to understand and not to mention trading stocks has been a great side hussle
With profficiency in Python and JavaScript, programming has always been extremely important to me as well as web and app developement from HTML and CSS to the many app frameworks that exist for IOS and Android, it has always been a fun side project ot pursue.
Before, finance and technology, I am an activist at heart always doing my best to positively impact the communities I'm in. I am often present at many meaningful protests, confrences and even conversation regarding social inequality however, I hope that down the line I can do much more, using both my passion in tech and finance
While I don't believe what school you go to defines your wit or inteligence, in the field of fin-tech, going to great school helps so I plan to persue a strong education in order to open up more opportunities for me.


--- layout: post title: 'Ep. 6: Jacob Scott Moses - The Not-Boring Tech Writer' date: 2016-11-23 16:09:35.000000000 -06:00 type: post parent_id: '0' published: true password: '' status: publish categories: - Podcast tags: [] meta: _edit_last: '1' slide_template: default _at_widget: '1' _yoast_wpseo_content_score: '30' fw:opt:ext:pb:page-builder:json: "[]" fw_options: a:9:{s:12:"page-builder";a:2:{s:4:"json";s:2:"[]";s:14:"builder_active";b:0;}s:9:"title_bar";s:7:"default";s:15:"footer_settings";s:7:"default";s:12:"header_style";a:2:{s:6:"option";s:0:"";s:11:"transparent";a:2:{s:16:"background_color";s:21:"rgba(255,255,255,0.3)";s:12:"border_color";s:0:"";}}s:12:"social_icons";s:0:"";s:12:"contact_info";s:0:"";s:12:"slider_above";a:2:{s:6:"option";s:2:"no";s:3:"yes";a:2:{s:5:"slide";s:1:"c";s:13:"scroll_effect";a:1:{s:6:"option";s:0:"";}}}s:22:"seo-titles-metas-title";s:0:"";s:28:"seo-titles-metas-description";s:0:"";} _yoast_wpseo_primary_category: '' _yoast_wpseo_post_image_cache: a:0:{} author: login: superuser email<EMAIL_ADDRESS>display_name: Administrator first_name: '' last_name: '' ---
We sat down with Jacob Scott Moses, a technical writer working remote for Rainmaker Digital out of Colorado, and talked about writing, podcasting, urban planning, and contributing to your community.
Show Notes
The Not Boring Tech Writer Podcast: https://itunes.apple.com/us/podcast/the-not-boring-tech-writer/id1093182479?mt=2
Parksify Podcast: https://itunes.apple.com/us/podcast/parksify-podcast/id1155954249?mt=2
Jacob's Website: http://jacobmoses.com
Rainmaker Digital: http://rainmakerdigital.com
Twitter: https://twitter.com/jacobscottmoses
Facebook: https://www.facebook.com/jake.moses02
LinkedIn: https://www.linkedin.com/in/jacob-moses-7a42343a
[soundcloud url="https://api.soundcloud.com/tracks/294482190" params="auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&visual=true" width="100%" height="450" iframe="true" /]


{% extends "layout.html" %} {% block content %}
Pneumonia is an infection of one or both of the lungs caused by bacteria, viruses, or fungi. It is a serious infection in which the air sacs fill with pus and other liquid. Lobar pneumonia affects one or more sections (lobes) of the lungs.
Malaria is a serious and sometimes fatal disease caused by a parasite that commonly infects a certain type of mosquito which feeds on humans. People who get malaria are typically very sick with high fevers, shaking chills, and flu-like illness. Four kinds of malaria parasites infect humans: Plasmodium falciparum, P.


|
hcash
2.0.0
hcash
|
#include <glua_lutil.h>
Public Member Functions | |
| TimeDiff (bool start_now=true) | |
| void | start () |
| void | end () |
| std::chrono::duration< double > | diff_time (bool end_time=true) |
| double | diff_timestamp (bool end_time=true) |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |


Trainer.
Trainer.A trainer takes a Machine and is able to train this machine on a given dataset with the train() method. For each machine, it should exist a trainer which knows how to train this machine. Testing the machine is possible with the test() method.
Given a List of measurers, and, if you want, a train DataSet (else NULL)
Returns an allocator to all the memory allocated by the function. You have to delete this allocator by yourself.
Alphabetic index HTML hierarchy of classes or Java


I'm an Engineer interesting in distributed system and other cutting edge computer technologies.
Check out my LinkedIn profile for an overview of my professional experience. If you want to connect, mention you came from my website and I'll add you back!
Take a look at some some of my code on GitHub https://github.com/wesleylima
Email me<EMAIL_ADDRESS>...and check back soon for the hottest takes in Florida


King Cove is located 600nm SW of Anchorage on the southern coast of the Alaska Peninsula. It is home to a large fish processing plant.
Position 55° 03'06"N, 162° 19'10"W
Contact the Harbour Master on VHF channel 16.
Yachts can moor in the old harbour.
Showers and toilets are in the Harbour Master's building.
Water, electricity and fuel are available.
There are two supermarkets here, one by the wharf and another in the town.
Last updated April 2016.


An implementation of the Diaspora cluster-generation system (as specified by VSCA Publishing). You may click on the words of the application title for more information.
So, in general, blue/gold is good; red/grey is bad.
There's no green because I'm trying to make it color-blind-friendly (at least, the most common form).
On the "Params" tab, enter the number of star systems in your cluster and hit the "Go!" button.
You can rearrange the nodes of the generated cluster map by dragging them (also, zoom and pan the map view by dragging its whitespace and using the mouse scroll wheel), but, at this time, those changes are ephemeral as all get-out, so don't put too much effort into it except as a busy-box kind of thing while you're on a conference call.
To access clusters in the cloud (sharing will be implemented later), you'll need to log in on the "Session" tab. Currently, only Google and "plain" logins are implemented. I might implement a Facebook login or a Twitter login later, if there's demand.
The rest of this is probably more than you want to know about an irritating login glitch.
Logging in works but is a bit glitchy at the moment, because the UI might not accurately update to reflect the fact that you're logged in. Your current user id should be displayed on the "Session" tab, but I guess I'm Doing It Wrong, because another UI update cycle (such as that triggered by generating a new cluster) sometimes is required for the Session tab UI to properly update.
In case you think you're logged in but the UI doesn't show it, to verify that you're logged in, if you have previously saved clusters, you should see them on the "Params" tab. (Alternatively, you can generate a new cluster and look again at the "Session" tab, where you should see your user id. If you already generated a spectacularly awesome cluster and you want to preserve it (a sketchy proposition, given that this is alpha software), see XML section below.)
If you hit "Login", and you get a prompt to enter your password (or pick a user id and then enter a password), you're almost certainly in, even though the UI might not update properly.
For the Google login, if you're logged in to Google on another web page, the login process here should automatically pick that up (when you hit the "Login" button).
Once you're logged in, you stay logged in, even between sessions, until you hit the "Logout" button.
If you're logged in, on the "Session" tab, enter a name for the cluster and hit "Save"
Note that there is also the possibility of extracting the cluster as XML, possibly for use in another cluster-generation system. See the "XML" tab.
When you have a great cluster and you're not sure you're logged in and you don't want to lose your cluster, save the XML. Then, when you get logged in, you can paste your saved XML back into the XML box and blithely continue.
On the "Params" tab, hit the orange "Load" button on the left side of the row of a cluster you want to edit.
On the "Params" tab, hit the red "Delete" button on the right side of the row of a cluster you want to delete.
On the "Cluster" tab, you can hit the "Edit" button at the right end of the row corresponding to a star system. The button will change to a "Done" button, which will end edit mode. However, you will still need to save the cluster to preserve your edits beyond your session.
Once the row is in Edit mode, you can change the star system's name or its aspects, or enter free-form notes about the system.
Finally, if you don't like the layout generated, you can drag the cluster nodes around to create a better layout. The canvas can be panned by clicking and dragging on white space, and it can be zoomed with the mouse scroll wheel. At this time, any changes you make will not be saved (even if you switch to another tab), so don't spend too much effort on rearranging the cluster. (Saving geometry changes will come in the future.)
I intend to keep a list of credits here (assuming I get contributions, which, ya know, who knows? ¯\_(ツ)_/¯ ). I'm happy to field suggestions, observations, complaints, pull requests, all that.
Graphical cluster notations were inspired by posts on the Google+ Diaspora community (specifically, Jeff Miller's notations). Search for "#clustermania" in the community.
Available at: GitHub: JohnL4/Diaspora-ng
If you look at it, you might (justifiably) come to the conclusion that it's a steaming, greasy pile of awfulness, but so be it. This ain't my day job. I was a Java web developer way back in the pre-Web-2.0 days and I'm like Rip van Winkle, having woken up and now attempting to come to grips with the new world.
This is what's called a "JAM" app in some corners of the internets: Javascript, APIs, Markup; there is no back-end (for now). See https://jamstack.org/ and https://www.netlify.com/ for more info.


Select the programming languages you know. (You could also
add all we know
.)
Tag text box
Java
Typeahead text box
Normal text box


Below, a custom element is defined. You can't see it because the HTML is a template element.
Here is an instance of the custom element:
See usage here:
Source


"""Module for linear autonomous pool models."""
from __future__ import division
from sympy import symbols, Matrix, exp, ones, diag, simplify, eye, log
from math import factorial, sqrt
import numpy as np
from scipy.linalg import expm
from scipy.optimize import brentq
from . import phase_type
from .dtmc import DTMC
from .helpers import entropy
#############################################
# Linear autonomous compartment model class #
# d/dt x(t) = Bx(t) + u #
#############################################
def _age_vector_dens(u, B, Qt):
"""Return the (symbolic) probability density vector of the compartment ages.
Args:
u (SymPy dx1-matrix): external input vector
B (SymPy dxd-matrix): compartment matrix
Qt (SymPy dxd-matrix): Qt = :math:`e^{t\\,B}`
Returns:
SymPy dx1-matrix: probability density vector of the compartment ages
:math:`f_a(y) = (X^\\ast)^{-1}\\,e^{y\\,B}\\,u`
"""
xss = -B.inv()*u
X = diag(*xss)
return X.inv()*Qt*u
def _age_vector_cum_dist(u, B, Qt):
"""Return the (symbolic) cumulative distribution function vector of the
compartment ages.
Args:
u (SymPy dx1-matrix): external input vector
B (SymPy dxd-matrix): compartment matrix
Qt (SymPy dxd-matrix): Qt = :math:`e^{t\\,B}`
Returns:
SymPy dx1-matrix: cumulative distribution function vector of the
compartment ages
:math:`f_a(y)=(X^\\ast)^{-1}\\,B^{-1}\\,(e^{y\\,B}-I)\\,u`
"""
d = B.rows
xss = -B.inv()*u
X = diag(*xss)
return X.inv()*B.inv()*(Qt-eye(d))*u
def _age_vector_nth_moment(u, B, n):
"""Return the (symbolic) vector of nth moments of the compartment ages.
Args:
u (SymPy dx1-matrix): external input vector
B (SymPy dxd-matrix): compartment matrix
n (positive int): order of the moment
Returns:
SymPy dx1-matrix: vector of nth moments of the compartment ages
:math:`\\mathbb{E}[a^n]=(-1)^n\\,n!\\,X^\\ast)^{-1}\\,B^{-n}\\,x^\\ast`
See Also:
:func:`_age_vector_exp`: Return the (symbolic) vector of expected values
of the compartment ages.
"""
xss = -B.inv()*u
X = diag(*xss)
return (-1)**n*factorial(n)*X.inv()*(B.inv()**n)*xss
def _age_vector_exp(u, B):
"""Return the (symbolic) vector of expected values of the compartment ages.
Args:
u (SymPy dx1-matrix): external input vector
B (SymPy dxd-matrix): compartment matrix
Returns:
SymPy dx1-matrix: vector of expected values of the compartment ages
:math:`\\mathbb{E}[a] = -(X^\\ast)^{-1}\\,B^{-1}\\,x^\\ast`
See Also:
:func:`_age_vector_nth_moment`: Return the (symbolic) vector of
``n`` th moments of the compartment ages.
"""
return _age_vector_nth_moment(u, B, 1)
def _age_vector_variance(u, B):
"""Return the (symbolic) vector of variances of the compartment ages.
Args:
u (SymPy dx1-matrix): external input vector
B (SymPy dxd-matrix): compartment matrix
Returns:
SymPy dx1-matrix: vector of variances of the compartment ages
:math:`\\sigma^2(a) = \\mathbb{E}[a^2] - (\\mathbb{E}[a])^2`
component-wise
See Also:
| :func:`_age_vector_exp`: Return the (symbolic) vector of expected
values of the compartment ages.
| :func:`_age_vector_nth_moment`: Return the (symbolic) vector of
``n`` th moments of the compartment ages.
"""
sv = _age_vector_nth_moment(u, B, 2)
ev = _age_vector_exp(u, B)
vl = [sv[i] - ev[i]**2 for i in range(sv.rows)]
return Matrix(sv.rows, 1, vl)
def _age_vector_sd(u, B):
"""Return the (symbolic) vector of standard deviations of the
compartment ages.
Args:
u (SymPy dx1-matrix): external input vector
B (SymPy dxd-matrix): compartment matrix
Returns:
SymPy dx1-matrix: vector of standard deviations of the compartment ages
:math:`\\sigma(a) = \\sqrt{\\sigma^2(a)}` component-wise
See Also:
:func:`_age_vector_variance`: Return the (symbolic) vector of variances
of the compartment ages.
"""
sdl = [sqrt(e) for e in _age_vector_variance(u, B)]
return Matrix(len(sdl), 1, sdl)
def _generalized_inverse_CDF(CDF, u, start_dist=1e-4, tol=1e-8):
"""Compute generalized inverse of a cumulative distribution function.
Can be used for quantile computation or generation of random variables
Args:
CDF (Python function): cumulative distribution function
start_dist (float): how far right from 0 to start looking for the
bisection interval,
defaults to 1e-4
tol (float): tolerance for brentq algorithm of numerical root search,
defaults to 1e-8
Returns:
int: smallest :math:`y` such that :math:`\\operatorname{CDF}(y)\\geq u`
"""
def f(a):
res = u-CDF(a)
return res
x1 = start_dist
# go so far to the right such that CDF(x1)>u, the bisect in interval [0, x1]
y1 = f(x1)
while y1 >= 0:
x1 = x1*2 + 0.1
y1 = f(x1)
if np.isnan(y1):
res = np.nan
else:
res = brentq(f, 0, x1, xtol=tol)
return res
[docs]def create_random_probability_vector(d: int, p: float) -> np.ndarray:
"""Create a random probability vector.
Args:
d: dimension of the random vector
p: probability of setting elements to nonzero value
Returns:
random probability vector `v` s.t.
- :math:`v_i \geq 0`
- :math:`\mathbb{P}(v_i>0) = p`
- :math:`\sum_i v_i=1`
"""
v = np.random.binomial(1, p, d)
v = v * np.random.uniform(0, 1, d)
if v.sum():
v = v / v.sum()
return np.random.permutation(v)
else:
# ensure that at least one entry is greater than 0
c = np.random.choice(np.arange(d))
v[c] = 1.0
return v
[docs]def create_random_compartmental_matrix(d: int, p: float) -> np.ndarray:
r"""Create a random invertible compartmental matrix.
Args:
d: dimension of the matrix (number of pools)
p: probability of existence of non-necessary connections
Returns:
random invertible compartmental matrix `B` s.t.
- all diagonal entries are nonpositive
- all off-diagonal entries are nonnegative
- all column sums are nonpositive
- :math:`B` is invertible
- :math:`-B_{ii} <= 1`
- :math:`\mathbb{P}(B_{ij}>0) = p` for :math:`i \neq j`
- :math:`\mathbb{P}(z_j)>0) = p`, where :math:`z_j = -\sum_i B_{ij}`
"""
V = np.zeros((d+1, d+1))
# add pools step by step, always keep the new pools connected to the
# previous smaller system
# pool 0 is the output pool
# build adjacency matrix
for n in range(1, d+1):
# random connections to smaller output-connected system
V[:n, n] = np.random.binomial(1, p, n)
# random connections from smaller output-connected system
V[n, :n] = np.random.binomial(1, p, n)
# ensure connection to smaller output-connected system
c = np.random.choice(np.arange(n))
V[c, n] = 1
# create B from adjacency matrix,
# repeat until det(B) is significantly different from 0
x = 0
while x < 1e-08:
# make random speeds from adjacencies
# (1 - uniform) to make sure the value will not be 0
# with a 0 value an essential connection could get lost
B = V * (1 - np.random.uniform(0, 1, (d+1)**2).reshape((d+1, d+1)))
# build diagonals
for j in range(B.shape[1]):
B[j, j] = -B[:, j].sum()
# ignore output pool 0
B = B[1:, 1:]
x = np.abs(np.linalg.det(B))
return B
############################################################################
[docs]class Error(Exception):
"""Generic error occuring in this module."""
pass
[docs]class NonInvertibleCompartmentalMatrix(Exception):
pass
[docs]class LinearAutonomousPoolModel(object):
"""General class of linear autonomous compartment models.
:math:`\\frac{d}{dt} x(t) = B\\,x(t) + u`
Notes:
- symbolic matrix exponential Qt = :math:`e^{t\\,B}`
cannot be computed automatically
- for symbolic computations it has to be given manually: model.Qt = ...
- otherwise only numerical computations possible
- symbolical computations can take very long, in particular
for complicated systems. An enforced purely numerical
treatment could then be the right choice; choose
``force_numerical=True``
- number of pools denoted by :math:`d`
- steady state vector denoted by
:math:`x^\\ast=-B^{-1}\\,u`
- normalized steady state vector denoted by
:math:`\\eta=\\frac{x^\\ast}{\\|x^\\ast\\|}`
- norm of a vector :math:`v` given by
:math:`\\|\\mathbf{v}\\| = \\sum\\limits_{i=1}^d |v_i|`
Attributes:
u (SymPy dx1-matrix): The model's external input vector.
B (SymPy dxd-matrix): The model's compartment matrix.
Qt (SymPy dxd-matrix): Qt = :math:`e^{t\\,B}`
"""
def __init__(self, u, B, force_numerical=False):
"""Return a linear autonomous compartment model with external
inputs u and (invertible) compartment matrix B.
Symbolical computations can take very long, in particular
for complicated systems. An enforced purely numerical
treatment could then be the right choice.
Args:
u (SymPy dx1-matrix): external input vector
B (SymPy dxd-matrix): invertible compartment matrix
force_numerical (boolean, optional):
if True do not try symbolical computations,
defaults to False
Remark:
While there are compartmental
systems that have singular matrices (systems with traps), most of the
methods of this class are only correct for invertible B.
We therefore reject singular matrices alltogether.
"""
# cover one-dimensional input
if (not hasattr(u, 'is_Matrix')) or (not u.is_Matrix):
u = Matrix(1, 1, [u])
if (not hasattr(B, 'is_Matrix')) or (not B.is_Matrix):
B = Matrix(1, 1, [B])
try:
B.inv()
except ValueError as e:
print(B)
raise NonInvertibleCompartmentalMatrix("""
The matrix B is not invertible.
While there are compartmental systems that have singular matrices
(systems with traps), most of the methods of this class are only
correct for invertible B.
We therefore reject singular matrices alltogether.
""")
self.B = B
self.u = u
# compute matrix exponential if no symbols are involved
if (not force_numerical) and ((B.is_Matrix) and (len(B.free_symbols) == 0)):
t = symbols('t')
self.Qt = exp(t*B)
[docs] @classmethod
def from_random(cls, d: int, p: float):
"""Create a random compartmental system.
Args:
d: dimension of the matrix (number of pools)
p: probability of having a connection between two pools
and of nonzero value in input vector
Returns:
randomly generated compartmental system
- `beta`: from :func:`create_random_probability_vector`
- `B: from :func:`~create_random_compartmental_matrix`
"""
beta = Matrix(create_random_probability_vector(d, p))
B = Matrix(create_random_compartmental_matrix(d, p))
return cls(beta, B, force_numerical=True)
# private methods
def _get_Qt(self, x):
"""Return matrix exponential of :math:`B` symbolically
if possible, or numerically.
Args:
x (nonnegative):
time at which the matrix exponential is to be evaluated
None: purely symbolic treatment
nonnegative value: symbolic treatment at time x if possible,
otherwise purely numeric treatment
Returns:
Sympy or NumPy dxd-matrix: :math:`e^{x\\,B}
Raises:
Error: If purely symbolic treatment is intended by no symbolic
matrix exponential is available.
"""
if x is None:
# purely symbolic case
if not hasattr(self, 'Qt'):
raise(Error(
'No matrix exponential given for symbolic calculations'))
Qt = self.Qt
else:
# numerical case
if hasattr(self, 'Qt'):
# if self.Qt exists, calculate symbolically and substitute t by
# time
t = symbols('t')
Qt = self.Qt.subs({t: x})
else:
# purely numerical calculation
B = self.B
D = np.array([[B[i,j] for j in range(B.cols)]
for i in range(B.rows)], dtype='float64') * float(x)
Qt = expm(D)
return Qt
# public methods
@property
def beta(self):
"""Return the initial distribution of the according Markov chain.
Returns:
SymPy or numerical dx1-matrix:
:math:`\\beta = \\frac{u}{\\|u\\|}`
"""
return self.u/sum([e for e in self.u])
@property
def xss(self):
"""Return the (symbolic) steady state vector.
Returns:
SymPy or numerical dx1-matrix:
:math:`x^\\ast = -B^{-1}\\,u`
"""
return -self.B.inv()*self.u
@property
def eta(self):
"""Return the initial distribution of the Markov chain according to
system age.
Returns:
SymPy or numerical dx1-matrix:
:math:`\\eta = \\frac{x^\\ast}{\\|x^\\ast\\|}`
"""
return self.xss/sum([e for e in self.xss])
# transit time
[docs] def T_cum_dist_func(self, time=None):
"""Return the cumulative distribution function of the transit time.
Args:
time (nonnegative, optional):
time at which :math:`F_T` is to be evaluated,
defaults to None: purely symbolic treatment
Returns:
SymPy expression or numerical value: cumulative distribution
function of the transit time (evaluated at time)
See Also:
:func:`.phase_type.cum_dist_func`: Return the (symbolic) cumulative
distribution function of phase-type.
"""
Qt = self._get_Qt(time)
return phase_type.cum_dist_func(self.beta, self.B, Qt)
[docs] def T_density(self, time=None):
"""Return the probability density function of the transit time.
Args:
time (nonnegative, optional):
time at which :math:`f_T` is to be evaluated,
defaults to None: purely symbolic treatment
Returns:
SymPy expression or numerical value: probability density
function of the transit time (evaluated at time)
See Also:
:func:`.phase_type.density`: Return the (symbolic) probability
density function of the phase-type distribution.
"""
Qt = self._get_Qt(time)
return phase_type.density(self.beta, self.B, Qt)
@property
def T_expected_value(self):
"""Return the (symbolic) expected value of the transit time.
See Also:
:func:`.phase_type.expected_value`: Return the (symbolic) expected
value of the phase-type distribution.
"""
return phase_type.expected_value(self.beta, self.B)
@property
def T_standard_deviation(self):
"""Return the (symbolic) standard deviation of the transit time.
See Also:
:func:`.phase_type.standard_deviation`: Return the (symbolic)
standard deviation of the phase-type distribution.
"""
return phase_type.standard_deviation(self.beta, self.B)
@property
def T_variance(self):
"""Return the (symbolic) variance of the transit time.
See Also:
:func:`.phase_type.variance`: Return the (symbolic) variance of
the phase-type distribution.
"""
return phase_type.variance(self.beta, self.B)
[docs] def T_nth_moment(self, n):
"""Return the (symbolic) ``n`` th moment of the transit time.
Args:
n (positive int): order of the moment
Returns:
SymPy expression or numerical value: :math:`\mathbb{E}[T^n]`
See Also:
:func:`.phase_type.nth_moment`: Return the (symbolic) ``n`` th
moment of the phase-type distribution.
"""
return phase_type.nth_moment(self.beta, self.B, n)
[docs] def T_quantile(self, q, tol=1e-8):
"""Return a numerical quantile of the transit time distribution.
The quantile is computed by a numerical inversion of the
cumulative distribution function.
Args:
q (between 0 and 1): probability mass to be left to the quantile
q = 1/2 computes the median
tol (float): tolerance for brentq algorithm of numerical
root search, defaults to 1e-8
Returns:
float: The smallest :math:`y` such that :math:`F_T(y)\\geq q`
See Also:
:func:`T_cum_dist_func`: Return the cumulative distribution
function of the transit time.
"""
CDF = lambda t: float(self.T_cum_dist_func(t))
try:
res = _generalized_inverse_CDF(CDF, q, tol=tol)
except TypeError as err:
raise Error("Quantiles cannot be computed symbolically.") from err
return res
# system age
[docs] def A_cum_dist_func(self, age=None):
"""Return the cumulative distribution function of the system age.
Args:
age (nonnegative, optional):
age at which :math:`F_A` is to be evaluated,
defaults to None: purely symbolic treatment
Returns:
SymPy expression or numerical value: cumulative distribution
function of PH(:math:`\\eta`, :math:`B`)
(evaluated at age)
See Also:
:func:`.phase_type.cum_dist_func`: Return the (symbolic) cumulative
distribution function of phase-type.
"""
Qt = self._get_Qt(age)
t, y = symbols('t y')
return phase_type.cum_dist_func(self.eta, self.B, Qt).subs({t:y})
[docs] def A_density(self, age=None):
"""Return the probability density function of the system age.
Args:
age (nonnegative, optional):
age at which :math:`f_A` is to be evaluated,
defaults to None: purely symbolic treatment
Returns:
SymPy expression or numerical value: probability density function
of PH(:math:`\\eta`, :math:`B`) (evaluated at age)
See Also:
:func:`.phase_type.density`: Return the (symbolic) probability
density function of the phase-type distribution.
"""
Qt = self._get_Qt(age)
t, y = symbols('t y')
return phase_type.density(self.eta, self.B, Qt).subs({t:y})
@property
def A_expected_value(self):
"""Return the (symbolic) expected value of the system age.
Returns:
SymPy expression or numerical value: expected value of
PH(:math:`\\eta`, :math:`B`)
See Also:
:obj:`.phase_type.expected_value`: Return the (symbolic) expected
value of the phase-type distribution.
"""
t, y = symbols('t y')
return phase_type.expected_value(self.eta, self.B).subs({t:y})
@property
def A_standard_deviation(self):
"""Return the (symbolic) standard deviation of the system age.
Returns:
SymPy expression or numerical value: standard deviation of
PH(:math:`\\eta`, :math:`B`)
See Also:
:func:`.phase_type.standard_deviation`: Return the (symbolic)
standard deviation of the phase-type distribution.
"""
return phase_type.standard_deviation(self.eta, self.B)
@property
def A_variance(self):
"""Return the (symbolic) variance of the system age.
Returns:
SymPy expression or numerical value: variance of
PH(:math:`\\eta`, :math:`B`)
See Also:
func:`.phase_type.variance`: Return the (symbolic) variance of the
phase-type distribution.
"""
return phase_type.variance(self.eta, self.B)
[docs] def A_nth_moment(self, n):
"""Return the (symbolic) ``n`` th moment of the system age.
Args:
n (positive int): order of the moment
Returns:
SymPy expression or numerical value: ``n`` th moment of
PH(:math:`\\eta`, :math:`B`)
See Also:
:func:`.phase_type.nth_moment`: Return the (symbolic) ``n`` th
moment of the phase-type distribution.
"""
return phase_type.nth_moment(self.eeta, self.B, n)
[docs] def A_quantile(self, q, tol=1e-8):
"""Return a numerical quantile of the system age distribution.
The quantile is computed by a numerical inversion of the
cumulative distribution function.
Args:
q (between 0 and 1): probability mass to be left to the quantile
q = 1/2 computes the median
tol (float): tolerance for brentq algorithm of numerical
root search, defaults to 1e-8
Raises:
Error: if attempt is made to compute quantiles symbolically
Returns:
float: smallest :math:`y` such that :math:`F_A(y)\\geq q`
See Also:
:func:`A_cum_dist_func`: Return the cumulative distribution
function of the system age.
"""
CDF = lambda t: float(self.A_cum_dist_func(t))
try:
res = _generalized_inverse_CDF(CDF, q, tol=tol)
except TypeError as err:
raise Error("Quantiles cannot be computed symbolically.") from err
return res
# compartment age
[docs] def a_cum_dist_func(self, age=None):
"""Return the cumulative distribution function vector of the
compartment ages.
Args:
age (nonnegative, optional):
age at which :math:`F_a` is to be evaluated,
defaults to None: purely symbolic treatment
Returns:
SymPy or numerical dx1-matrix: :math:`F_a` (evaluated at age)
:math:`F_a(y) = (X^\\ast)^{-1}\\,B^{-1}\\,`
:math:`(e^{y\\,B}-I)\\,u`
"""
Qt = self._get_Qt(age)
t, y = symbols('t y')
return _age_vector_cum_dist(self.u, self.B, Qt).subs({t:y})
[docs] def a_density(self, age=None):
"""Return the probability density function vector of the
compartment ages.
Args:
age (nonnegative, optional):
age at which :math:`f_a` is to be evaluated,
defaults to None: purely symbolic treatment
Returns:
SymPy or numerical dx1-matrix: :math:`f_a` (evaluated at age)
:math:`f_a(y) = (X^\\ast)^{-1}\\,`
:math:`e^{y\\,B}\\,u`
"""
Qt = self._get_Qt(age)
t, y = symbols('t y')
return _age_vector_dens(self.u, self.B, Qt).subs({t:y})
@property
def a_expected_value(self):
"""Return the (symbolic) vector of expected values of the
compartment ages.
Returns:
SymPy dx1-matrix:
:math:`\\mathbb{E}[a] = -(X^\\ast)^{-1}\\,`
:math:`B^{-1}\\,x^\\ast`
"""
t, y = symbols('t y')
return _age_vector_exp(self.u, self.B)
@property
def a_standard_deviation(self):
"""Return the (symbolic) vector of standard deviations of the
compartment ages.
Returns:
SymPy dx1-matrix:
:math:`\\sigma(a) = \\sqrt{\\sigma^2(a)}` component-wise
"""
return _age_vector_sd(self.u, self.B)
@property
def a_variance(self):
"""Return the (symbolic) vector of variances of the compartment ages.
Returns:
SymPy dx1-matrix:
:math:`\\sigma^2(a) = \\mathbb{E}[a^2]`
:math:`- (\\mathbb{E}[a])^2` component-wise
"""
return _age_vector_variance(self.u, self.B)
[docs] def a_nth_moment(self, n):
"""Return the (symbolic) vector of the ``n`` th moments of the
compartment ages.
Args:
n (positive int): order of the moment
Returns:
SymPy or numerical dx1-matrix:
:math:`\\mathbb{E}[a^n] = (-1)^n\\,n!\\,(X^\\ast)^{-1}`
:math:`\\ ,B^{-n}\\,x^\\ast`
"""
return _age_vector_nth_moment(self.beta, self.B, n)
[docs] def a_quantile(self, q, tol=1e-8):
"""Return a vector of numerical quantiles of the pool age distributions.
The quantiles is computed by a numerical inversion of the
cumulative distribution functions.
Args:
q (between 0 and 1): probability mass to be left to the quantile
q = 1/2 computes the median
tol (float): tolerance for brentq algorithm of numerical
root search, defaults to 1e-8
Returns:
numpy.array: vector :math:`y=(y_1,\\ldots,y_d)` with
:math:`y_i` smallest value such that :math:`F_{a_i}(y_i)\\geq q`
See Also:
:func:`a_cum_dist_func`: Return the cumulative distribution function
vector of the compartment ages.
"""
d = self.B.rows
res = np.nan * np.zeros(d)
try:
for pool in range(d):
CDF = lambda t: float(self.a_cum_dist_func(t)[pool])
res[pool] = _generalized_inverse_CDF(CDF, q, tol=tol)
except TypeError as err:
raise Error("Quantiles cannot be computed symbolically.") from err
return res
# Laplacians for T and A
@property
def T_laplace(self):
"""Return the symbolic Laplacian of the transit time.
Returns:
SymPy expression: Laplace transform of the probability density of
PH(:math:`\\beta`, :math:`B`)
See Also:
:obj:`.phase_type.laplace`: Return the symbolic Laplacian of the
phase-type distribtion.
"""
return simplify(phase_type.laplace(self.beta, self.B))
@property
def A_laplace(self):
"""Return the symbolic Laplacian of the system age.
Returns:
SymPy expression: Laplace transform of the probability density of
PH(:math:`\\eta`, :math:`B`)
See Also:
:obj:`.phase_type.laplace`: Return the symbolic Laplacian of the
phase-type distribtion.
"""
return simplify(phase_type.laplace(self.eta, self.B))
# release
@property
def r_compartments(self):
"""Return the (symbolic) release vector of the system in steady state.
Returns:
SymPy or numerical dx1-matrix: :math:`r_j = z_j \\, x^\\ast_j`
See Also:
| :func:`.phase_type.z`: Return the (symbolic) vector of rates
toward absorbing state.
| :obj:`xss`: Return the (symbolic) steady state vector.
"""
r = phase_type.z(self.B)
return Matrix(self.xss.rows, 1, [phase_type.z(self.B)[i]*self.xss[i]
for i in range(self.xss.rows)])
@property
def r_total(self):
"""Return the (symbolic) total system release in steady state.
Returns:
SymPy expression or numerical value:
:math:`r = \\sum\\limits_{j=1}^d r_j`
See Also:
:obj:`r_compartments`: Return the (symbolic) release vector of the
system in steady state.
"""
return sum(self.r_compartments)
@property
def absorbing_jump_chain(self):
"""Return the absorbing jump chain as a discrete-time Markov chain.
The generator of the absorbing chain is just given by :math:`B`, which
allows the computation of the transition probability matrix :math:`P`
from :math:`B=(P-I)\\,D` with :math:`D` being the diagonal matrix with
diagonal entries taken from :math:`-B`.
Returns:
:class:`~.DTMC.DTMC`: :class:`DTMC` (beta, P)
"""
# B = (P - I) * D
d = self.B.rows
D = diag(*[-self.B[j,j] for j in range(d)])
P = self.B * D**(-1) + eye(d)
return DTMC(self.beta, P)
@property
def ergodic_jump_chain(self):
"""Return the ergodic jump chain as a discrete-time Markov chain.
The generator is given by
.. math::
Q = \\begin{pmatrix}
B & \\beta \\\\
z^T & -1
\\end{pmatrix}
and the corresponding transition probability matrix :math:`P_Q` can
then be obtained from :math:`Q=(P_Q-I)\\,D_Q`, where :math:`D_Q` is the
diagonal matrix with entries from the diagonal of :math:`-Q`.
Returns:
:class:`~.DTMC.DTMC`: :class:`DTMC` (beta_ext, Q) with
beta_ext = (beta, 0)
"""
B = self.B
d = B.rows
lor = []
for i in range(d):
row = list(B[i,:]) + [self.beta[i]]
lor.append(row)
row = list(phase_type.z(B)) + [-1]
lor.append(row)
# (d+1)x(d+1) matrix
# B beta
# z^T -1
Q = lor
P = Matrix(Q)
for j in range(d+1):
for i in range(d+1):
if Q[j][j] != 0:
if i != j:
P[i,j] = -Q[i][j]/Q[j][j]
else:
P[i,j] = 0
else:
if i != j:
P[i,j] = 0
else:
P[i,j] = 1
beta = Matrix(d+1, 1, list(self.beta) + [0])
return DTMC(beta, P)
#fixme: to be tested
@property
def entropy_per_jump(self):
"""Return the entropy per jump.
Returns:
SymPy expression or float: :math:`\\theta_J=`
:math:`\\sum\\limits_{j=1}^{d+1} \\pi_j`
:math:`\\sum\\limits_{i=1}^{d+1}-p_{ij}\\,\\log p_{ij}`
:math:`+\\sum\\limits_{j=1}^d \\pi_j\\,(1-\\log -b_{jj})`
:math:`+\\pi_{d+1}\\,\\sum\\limits_{i=1}^d`
:math:`-\\beta_i\\,\\log\\beta_i`
Notes:
- :math:`\\pi` is the stationary distribution of the ergodic
jump chain.
- :math:`\\theta_J=` entropy of ergodic jump chain +
entropy of sojourn times (no stay in environmental
compartment :math:`d+1`)
See Also:
:obj:`~.DTMC.DTMC.stationary_distribution`:
Return the (symbolic) stationary distribution.
"""
d = self.B.rows
P = self.ergodic_jump_chain.P
pi = self.ergodic_jump_chain.stationary_distribution
theta_jumps = self.ergodic_jump_chain.ergodic_entropy
theta_stays = 0
for j in range(d+1):
x = 0
if j == d:
# no entropy for stay in environment
x += 0
else:
# differential entropy of exponential distribution
x += (1-log(-self.B[j,j]))
x *= pi[j]
theta_stays += x
return theta_jumps + theta_stays
#fixme: to be tested
@property
def entropy_per_cycle(self):
"""Return the entropy per cycle.
Returns:
SymPy expression or float: entropy per jump
:math:`\\times` expected number of jumps per cycle
See Also:
| :obj:`entropy_per_jump`: Return the entropy per jump.
| :obj:`~.DTMC.DTMC.expected_number_of_jumps`:
Return the (symbolic) expected number of jumps before absorption.
"""
theta_per_jump = self.entropy_per_jump
jumps = self.absorbing_jump_chain.expected_number_of_jumps
# add one jump from the environment into the system
return theta_per_jump * (jumps+1)
#fixme: to be tested
@property
def entropy_rate(self):
"""Return the entropy rate (entropy per unit time).
Returns:
SymPy expression or float: entropy per cycle
:math:`\\cdot\\frac{1}{\\mathbb{E}T}`
See Also:
| :obj:`entropy_per_cycle`: Return the entropy per cylce.
| :obj:`T_expected_value`: Return the (symbolic) expected
value of the transit time.
"""
# the entropy rate is the entropy per unit time
# thus the entropy per cycle over cycle length
theta_cycle = self.entropy_per_cycle
return theta_cycle/self.T_expected_value


make maps memorable
We’re working on easy-to-implement, customizable tools for search, rendering, and routing.
Tangram
Tangram is a flexible, hackable mapping engine, designed for real-time rendering of 2D and 3D maps using vector tiles and the OpenGL family of graphics libraries. Built around OpenStreetMap data, Tangram provides optional control over almost every aspect of the map-making process, including cartography, lighting, and geometry customization.
LEARN MORE VIEW ON GITHUBMapzen Search
Mapzen Search is a modern geocoding and place search service based on Mapzen's open source geocoder and powered by open data. It's used to transform the way people talk about places—with names and addresses—into geographic coordinates, and to translate geographic coordinates into recognizable names of places.
LEARN MORE VIEW ON GITHUBMapzen Turn-by-Turn
Mapzen Turn-by-Turn is an open-source routing service for client-side routing applications and hosted solutions.
LEARN MORE VIEW ON GITHUBVector Tile Service
Vector tiles are awesome for generating real-time renderings of map data. We wanted to make it easier for developers to experiment with them without having to set everything up themselves, so we're running a free vector tile service for OSM base layer data that lets you get right to work.
LEARN MORE VIEW ON GITHUB


a designer
Hi! I'm an experienced graphic designer who was born in New Jersey, studied design in Philadelphia and currently resides in Atlanta! As a child I was constantly being told that I had the gift of creativity - I took those comments to heart and have since been working to make the world a little more thoughtfully designed. While my background is rooted in print media, time and technological progress have shifted my focus to user experience, interface and web design.
I cut my teeth on tangible marketing collateral…but the digital world shift makes it even more important to have intelligently designed print media.
No one likes to stumble around on a website blindly. It needs to be pretty and functional. Let’s make the internet beautiful together.
Clear focus of a brand's core values, strategy and vision is not only important to the customer; its important to the brand istelf. How you present to the market needs to be clear and calculated.
I am a hungry designer who is ready to take on the world;
reach out and let's make the world a more nicely designed place.
856-305-9388


Ruby
Ruby is an all purpose scripting language with very light-weight syntax, because of this it is ideal for rapid software developement and experimentation.
Ruby Rescources:
# Comment text
JavaScript
JavaScript is an all purpose scripting language with medium-weight syntax, because of this it is well suited for experimentation as well as large scale projects. It has a large base of external libraries to pull from including jQuery, three.js, underscore, and lodash. The libraries lodash and underscore make it's it almost as great a scripting language as ruby by providing many pre-built functions that mirror many of the enumerables and methods availible in ruby.
JavaSCript Rescources:
# Comment text
CSS
CSS is used to manipulate and change the various properties of all html elements. CSS is able make specifications to a group, subset of elements or a particular element through the use of selectors.
CSS Resources:
Prism
Prism Resources:
Usage
| Language | Class |
| HTML | language-markup |
| CSS | language-css |
| JavaScript | language-javascript |
| CoffeeScript | language-coffeescript |
| PHP | language-php |
| Ruby | language-ruby |
| Go | language-go |


Moments in the life of Zinder
From the view of her litter box custodian
Zinder is a wild Lynx Point who was found by her caretaker whilst working on a farm. He brought her home after harvest to save her from freezing during the Winter.
Here are some activities Zinder enjoys
- Gazing into the horizon from the porch
- Laying majestically around the house, switching locations often
- Being scratched behind her ears and under her chin
- Doing backflips in attempt to catch dandelion pollen
Here are some things Zinder does not enjoy one bit
- An imperfectly clean water dish
- Seeing any portion of the bottom of the food dish
- New people and animals


CSS rules to specify families
To help cater Bus Mall magazine products to target customers, please click the item you are most likely to purchase. You will be shown three choices in each voting round. Results will be shown below.


| Pay Amount | Currency | Pay Type | Pay Mode | ||||||
| {{invoiceReport.paidDate | date:'dd-MM-yyyy'}} | {{invoiceReport.invoiceCode}} | {{invoiceReport.payAmount}} | {{invoiceReport.currency}} | {{invoiceReport.invoiceStatus}} | {{invoiceReport.paymentRefNo}} | {{invoiceReport.payType}} | {{invoiceReport.payMode}} | {{invoiceReport.payMethod}} | {{invoiceReport.payStatus}} |
| Pay Amount | Currency | Pay Type | Pay Mode | ||||||
| {{expenseReport.paidDate | date:'dd-MM-yyyy'}} | {{expenseReport.invoiceCode}} | {{expenseReport.payAmount}} | {{expenseReport.currency}} | {{expenseReport.invoiceStatus}} | {{expenseReport.paymentRefNo}} | {{expenseReport.payType}} | {{expenseReport.payMode}} | {{expenseReport.payMethod}} | {{expenseReport.payStatus}} |
| Name | Mobile | Invoice Amount | Refund Amount | |||
| {{consumerReport.name}} | {{consumerReport.email}} | {{consumerReport.mobile}} | {{consumerReport.invoices}} | {{consumerReport.refunded}} | {{consumerReport.invoiceAmt}} | {{consumerReport.refundAmt}} |
| Name | Mobile | Expense Amount | Refund Amount | |||
| {{supplierReport.name}} | {{supplierReport.email}} | {{supplierReport.mobile}} | {{supplierReport.expenses}} | {{supplierReport.refunded}} | {{supplierReport.expenseAmt}} | {{supplierReport.refundAmt}} |
| Code | Sale Quantity | Sale Amount | ||
| {{inventoryReport.code}} | {{inventoryReport.name}} | {{inventoryReport.rate}} | {{inventoryReport.saleQuantity}} | {{inventoryReport.saleAmt}} |
| Code | Sale Quantity | Sale Amount | ||
| {{assetReport.code}} | {{assetReport.name}} | {{assetReport.rate}} | {{assetReport.saleQuantity}} | {{assetReport.saleAmt}} |


A Search a Day Keeps the Doctor Not Away
Find a doctor in the Seattle region using the search below.
Doctor's Name:
Medical Issue:
Search
Search Results:


Welcome to the technical fest ADVIKA 2K18 in the campus of Adikavi Nannaya Unviersity. We are pleased and Excited to invite you all for the three day fest to be held on .On this occasion we Challenge your Ability and Knowledge over Technology and other Aspects with a mixture of your talents.It is a Platform to Show your Talent and Ideas to many others.So, Dont Let Go Away the Oppurtunity for many Events and Surprises are waiting for You.This Event is conducted by the College of Engineering, Adikavi Nannaya University, Rajamahendravaram.
The immense intention of organising the ADVIKA 2K18 is to recieve naive ideas of the students by providing a platform to exibit them and get awareness about the current technologies on 'how' principle rather than 'what'. To realize their stand of point in that aspect and improve their skills. ADVIKA aims at the student fraternity to utilize the opportunity to enhance/exibit their abilities and induce a different expirience.We Think You'll have fun!!!
Vice Chancellor,AKNU
Registrar,AKNU
Dean CDC,AKNU
Principal,
College Of Engineering,AKNU
HOD,Dept. of CSE,AKNU
Event Description.


Celebrated Zimbabwean Journalist, Haru Mutasa who works for Al Jazeera has social media in a frenzy after she posted a cryptic melancholic message on microblogging social network, Twitter, saying, ” She feels she will die young”
While some of Haru’s sentiments have been unpopular here and there, many of her critics and “twenemies”, in a rare show of solidarity and maturity, rushed to comfort her and have urged her employer Al Jazeera to check on her.
Social Media Personality Mike Tashaya posted on his account, ”
Patience Rumbi commented,
Michelle Mafusire Problem also commented,
Sometime back in mid-October, the decorated journalist who has worked for other influential organisations such as SABC and CNN, announced that she was going to quit Twitter as she found it to be abusive.
She posted then,
We here at iHarare pray that whatever she is going through, she will fight and not let it take away her shine.
To View and Apply for the latest Jobs and Vacancies in Zimbabwe, Please Visit our Sister websiteiHarare Jobs


Product Dimensions
Width: 24
Height: 15.5
Depth: 23
Product Warranty
Thank you for choosing Kingsley-Bate fine outdoor furniture. With proper use and care, we are confident that our product will provide you with years of trouble-free enjoyment. Your furniture comes with a limited warranty against manufacturer's defects. Standard warranty periods for each category of furniture are provided below.
To inquire about warranty coverage, please contact the retail store where the furniture was purchased.
TEAK FURNITURE
-
5 year warranty for residential applications
-
3 year warranty for commercial applications
-
1 year warranty for glass table tops, cushions, slings, and pillows
STAINLESS STEEL FURNITURE
-
3 year warranty for residential or commercial applications
-
1 year warranty for slings
WOVEN FURNITURE
-
3 year warranty for residential or commercial applications
-
1 year warranty for glass table tops, cushions, and pillows
UMBRELLAS/BASES
-
1 year umbrella warranty for residential or commercial applications
-
1 year umbrella base warranty for residential or commercial applications (corrosion not covered)


Experience
DEME – Dredging International 09/2011-PRESENT
Head of Project Launch Department - Zwijndrecht, Belgium 06/2020-PRESENT
Responsible for departments Dredge pipes & Cutter heads, Mobdemob, Lay-down HQ & Business Partner Procurement.
Accountable for the successful mobilization of operational critical mission equipment and to streamline procurement on projects.
- Coordinated the blue print design of the new Project Launch Department
- Initiated the DEME Safe Logistics project and prevented HiPo incidents from happening in 2020
- Transformed communication methods to re-align & focus workforce’s efforts to ensure operational logistic excellence.
- Designed & implemented a cost economical router to reduce transit costs by 3-5% (€1.5M/annum)
- Created & implemented the mobilization proposal to reduce TCO cost by 3-5% (€500k/annum)
Logistics Manager - Zwijndrecht, Belgium 02/2017-05/2020
Responsible for departments Dredge pipes & Cutter heads, mobdemob, Charter Desk, Transport, Warehouse & Shipment and Lay-down HQ.
Accountable for mobilization of operational critical mission equipment & distribution of procured goods
to projects.
- Set up & launched strategic programs per supply chain and identified key improvement projects
- Organized active wear follow up on project Tema to reduce wear by 10% (€150k)
- Reduced TCO by 4%(€250k/annum) by implementing an improved inventory policy
Coordinator Mission Equipment - Zwijndrecht, Belgium 09/2014-01/2017
Responsible for worldwide operational planning & life cycle management of mission critical equipment.
- Initiated turn-key solutions to deliver mission equipment first time right
- Implemented mobilization dashboards as single source of truth to significantly improve & centralize communication across departments & projects
Superintendent(SI)/Works Manager(WM) – Perth, AU / Bremen, DE / Onne, NI 12/2012-08/2014
Manage and successfully coordinate operations of production units on projects according to plan.
- Onne Port Expansion: Launched CTOW business unit to enter towing operations market
- Bremen Kohlenhafen: WM for backhoe dredge (BHD) Peter The Great
- Wheatstone project: SI for dry-dock operations of CSD Ambiorix (Singapore)
Production Engineer / Superintendent – Panama City, Panama 06/2012-11/2012
Responsible to explore & evaluate alternative dredge methods to optimize production.
- Developed & implemented a pressure release valve into dredge line to save 35% on delays (€300k)
- Reduced operational delays up to 30% by standardizing & communicating SOP’s with crew (€1.7M)
Project Engineer – Colonia Del Sacramento, Uruguay 09/2011-05/2012
Responsible to design and execute the test protocol for a high pressure water jetting prototype.
- Coordinated the installation of the prototype and successfully launched system into operation
- Gathered all relevant information and compiled it into an operator’s manual
TOYOTA Motor Europe (TME) - Zaventem, Belgium 08/2008-08/2011
Chassis Project Engineer
Responsible for the design & development of suspensions parts.
- Engineered a solution to a road noise design issue to resolve customer complaint problem
- Reduced costs on suspension parts (€100k/annum) by changing identifiers & materials used


Page titles
Rules
- Documents must have a page
<title>
that identify their main content.
Rationale
Document titles help users orientate themselves within web sites and apps. The document <title>
element content is often the first thing that a speech output user will hear. It acts as a confirmation of what page they have arrived at. Document titles commonly have the same content as the page's <h1>
element.
Techniques
Tests
| Procedure | Expected result | Type |
Examine the title text of each document by viewing the document source code and searching for the <title> element. |
The document title should describe the primary title of the document. | Manual |


:: com :: sun :: star :: ucb ::
|
| struct OpenCommandArgument |
|
- Description
- The argument for commands like "open", "update", and "synchronize".
- See also
- XCommandProcessor
|
| Elements' Details |
Mode
long Mode;
- Description
- A mode.
The value can be one of the OpenMode constants.
|
|
Priority
long Priority;
- Description
- The command's priority, in the range
0 (highest) to
65535 (lowest).
|
|
Sink
::com::sun::star::uno::XInterface Sink;
- Description
- The data sink to write the contents into (supporting either
::com::sun::star::io::XActiveDataSink,
::com::sun::star::io::XOutputStream or
::com::sun::star::io::XActiveDataStreamer).
XActiveDataSink and XOutputStream give the caller read-only
access to the contents. XActiveDataStreamer offers both read and
write access to the contents.
If an XActiveDataSink is supplied, the implementation of the command
needs to provide an implementation of an object implementing the
interface ::com::sun::star::io::XInputStream. It is
highly recommended that this object also implements the interface
::com::sun::star::io::XSeekable, if this can be done
without wasting resources (i.e. allocating huge memory buffers).
The implementation object has to be supplied to the data sink.
|
|
Properties
sequence< ::com::sun::star::beans::Property > Properties;
- Description
- The properties, for that the values shall be provided by the
DynamicResultSet returned by the command).
|
|
Top of Page
Copyright © 2013, The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache, the Apache feather logo, Apache OpenOffice and OpenOffice.org are trademarks of The Apache Software Foundation. Other names may be trademarks of their respective owners.


ORG_3000003 - has postal address representation
Label
has postal address representation
Alternate name
has address value
Sub property of
Definition
Specifies the postal address string for a postal address
Definition source
Michael Conlon https://orcid.org/0000-0002-1304-8447
Domain
Example
1210 NW 14th Ave; ;Gainesville; Fl; USA; 32601
Editor’s note
Regex pattern restriction for UPC email addresses
Term editor
Michael Conlon https://orcid.org/0000-0002-1304-8447


If you’re interested in your child learning about the sugar, salt, and fat content of certain foods, look no further than this fun app that invites kids to learn various foods and beverages such as pizza and soda.
This app helps kids understand that food provides energy through calories, and compares the number of calories eaten with the activity required to use that energy.
Looking for an easy-to-print handout for your nutrition or fitness class? Find materials for all ages here.
Discover hundreds of tasty, healthy, budget-friendly recipes for you and your family.
Find strategies for successful weight loss, what you should know about popular diets, and more.