diff --git a/404.html b/404.html index 765870edca..c009e5f265 100644 --- a/404.html +++ b/404.html @@ -10,8 +10,8 @@ - - + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

diff --git a/about/intro/index.html b/about/intro/index.html index 12f2ae2c4a..32858d7166 100644 --- a/about/intro/index.html +++ b/about/intro/index.html @@ -10,8 +10,8 @@ - - + +
Skip to main content

How does LAMP Platform Work?

@@ -25,6 +25,6 @@

The Dashboard<

The dashboard aggregates, analyzes, and displays data collected from the smartphone app. Dashboard information can be shared with clinicians, family members, and trusted peers. It allows clinicians, researchers, and patients to visualize data that is collected and aid in treatment and/or research.

Please note that LAMP requires at least Android 7 minimum and soon will require iOS 14 minimum to run on a smartphone.

Diagram of the LAMP Platform

-

+

\ No newline at end of file diff --git a/about/publications/index.html b/about/publications/index.html index 7d09931576..94881ef416 100644 --- a/about/publications/index.html +++ b/about/publications/index.html @@ -10,8 +10,8 @@ - - + +
Skip to main content

Publications with LAMP

@@ -65,6 +65,6 @@

Wisniewski Hannah, Henson Philip, Torous John. Using a Smartphone App to Identify Clinically Relevant Behavior Trends via Symptom Report, Cognition Scores, and Exercise Levels: A Case Series. Frontiers in Psychiatry. 10-2019-652. doi:10.3389/fpsyt.2019.00652

Digital Phenotyping for Spinal Cord Injury: Smartphone-based monitors for clinical utility

-
+
\ No newline at end of file diff --git a/about/users/index.html b/about/users/index.html index 377f0fa6be..e7ef2f344b 100644 --- a/about/users/index.html +++ b/about/users/index.html @@ -10,8 +10,8 @@ - - + +
Skip to main content

Who's using LAMP?

@@ -175,6 +175,6 @@

Univers

In this study we aim to use digital interventions to improve mental wellbeing in the general population, with a specific target of four groups that are particularly, but very differently, affected by the COVID-19 pandemic: people in isolation, students, athletes, and frontline clinical staff. Clinical staff will likely have limited flexibility in their daily routine, but those who can no longer work will have too much flexibility. We will capture digital phenotypes of participants as well as signals related to interventions like mood, anxiety, diet, sleep, steps etc (as noted above). We will compare a standard intervention (using the app to deliver generic advice and instructions about pre-defined interventions) with a personalised one (using information based on individual differences and preferences in a personalised and dynamic way). All data will be de-identified and made freely available to the scientific community at the end of the study.

-

To read more about this study, see here: PAIDEIA: Personalised Artificial Intelligence versus a Designed by Experts Individualised Approach

+

To read more about this study, see here: PAIDEIA: Personalised Artificial Intelligence versus a Designed by Experts Individualised Approach

\ No newline at end of file diff --git a/app/index.html b/app/index.html index 437ea39f13..50ab4e3394 100644 --- a/app/index.html +++ b/app/index.html @@ -10,8 +10,8 @@ - - + +
Skip to main content

Download mindLAMP

@@ -153,6 +153,6 @@

BetaEnroll in the Play Store beta for mindLAMP.
-

The Division of Digital Psychiatry continuously maintains the mindLAMP app for app store regulatory compliance through frequent updates and correspondence with Apple and Google.

+

The Division of Digital Psychiatry continuously maintains the mindLAMP app for app store regulatory compliance through frequent updates and correspondence with Apple and Google.

\ No newline at end of file diff --git a/assets/images/survey_edit_new-39b0849dc8c72d2a1840561e41b3af48.jpg b/assets/images/survey_edit_new-39b0849dc8c72d2a1840561e41b3af48.jpg new file mode 100644 index 0000000000..635d257556 Binary files /dev/null and b/assets/images/survey_edit_new-39b0849dc8c72d2a1840561e41b3af48.jpg differ diff --git a/assets/js/011dd25e.e95b3d47.js b/assets/js/011dd25e.3a085cfe.js similarity index 99% rename from assets/js/011dd25e.e95b3d47.js rename to assets/js/011dd25e.3a085cfe.js index 15b68fd22f..792e1ba082 100644 --- a/assets/js/011dd25e.e95b3d47.js +++ b/assets/js/011dd25e.3a085cfe.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2041],{4133:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"develop/couchdb-migration","title":"Migrating from CouchDB to MongoDB","description":"Please carefully read and replace the variables in this JS script before continuing:","source":"@site/docs/08-develop/11-couchdb-migration.md","sourceDirName":"08-develop","slug":"/develop/couchdb-migration","permalink":"/develop/couchdb-migration","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/08-develop/11-couchdb-migration.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":11,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"OAuth2/OIDC Support","permalink":"/develop/oauth_oidc"},"next":{"title":"Training Modules","permalink":"/develop/Training Modules/training-modules"}}');var a=t(74848),i=t(28453);const r={},c="Migrating from CouchDB to MongoDB",s={},d=[];function l(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"migrating-from-couchdb-to-mongodb",children:"Migrating from CouchDB to MongoDB"})}),"\n",(0,a.jsx)(n.p,{children:"Please carefully read and replace the variables in this JS script before continuing:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",metastring:'title="index.js"',children:"#!/usr/bin/env node\nconst es = require('event-stream')\nconst JSONStream = require('JSONStream')\nconst through2batch = require('through2-batch')\n//const nano = require('nano')('http://admin:REDACTED_PASSWORD@10.0.0.1:5984/') // STAGING\nconst nano = require('nano')('http://admin:REDACTED_PASSWORD@10.0.0.2:5984/') // PRODUCTION\nconst { MongoClient } = require('mongodb')\nconst MONGO_URL = 'mongodb://USERNAME_REDACTED:PASSWORD_REDACTED@CLUSTER_NAME_REDACTED.us-east-2.docdb.amazonaws.com:27017/LAMP?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false'\nconst DB_NAME = \"LAMP\"\n\n// MAKE THE REQUIRED COLLECTIONS AND INDEXES FIRST BEFORE LOADING DATA IN! \n/*\nconst REQUIRED_INDEXES = {\n \"researcher\": [\n { timestamp: 1 }, \n { timestamp: 1, _id: 1 }\n ],\n \"study\": [\n { timestamp: 1 }, \n { timestamp: 1, _id: 1 }, \n { timestamp: 1, _id: 1, _parent: 1 }\n ],\n \"participant\": [\n { timestamp: 1 }, \n { _parent: 1, timestamp: 1 }, \n { _id: 1, _parent: 1, timestamp: 1 }\n ],\n \"activity\": [\n { timestamp: 1 },\n { timestamp: 1, _parent: 1 },\n { _id: 1, timestamp: 1 },\n { timestamp: 1, _id: 1, _parent: 1 },\n ],\n \"sensor\": [\n { timestamp: 1 },\n { timestamp: 1, _parent: 1 },\n { _id: 1, timestamp: 1 },\n { timestamp: 1, _id: 1, _parent: 1 },\n ],\n \"activity_event\": [\n { _parent: -1, activity: -1, timestamp: -1 },\n { _parent: -1, timestamp: -1 },\n ],\n \"tag\": [\n { _parent: 1, type: 1, key: 1 }\n ],\n \"credential\": [\n { access_key: 1 }, \n { origin: 1 }, \n { origin: 1, access_key: 1 }\n ],\n \"sensor_event\": [\n { _parent: -1, sensor: -1, timestamp: -1 },\n { _parent: -1, timestamp: -1 },\n ],\n}\nfor (let [collection, indexes] of Object.entries(REQUIRED_INDEXES)) {\n console.dir([collection, indexes])\n db.collection(collection).createIndexes(indexes).catch(err => console.dir(err))\n}\n*/\n\n// IGNORE THIS, SEE BELOW INSTEAD\nconst ANALYTICS_IDS = []\nasync function migrateANALYTICS(db, pID) {\n let count = 0\n\tnano.use('sensor_event')\n\t\t.findAsStream({\n selector: {\n \"#parent\": pID,\n \"sensor\": \"lamp.analytics\",\n },\n sort: [{ timestamp: 'desc' }],\n limit: 100000\n })\n\t\t.on('error', (e) => console.error('error', e))\n\t\t.pipe(JSONStream.parse('docs.*'))\n .pipe(es.map((data, callback) => {\n data._deleted = false\n data._parent = data['#parent']\n delete data._rev\n delete data['#parent']\n callback(null, data)\n }))\n .pipe(through2batch.obj({ batchSize: 100000 }))\n\t\t.pipe(es.map((data, callback) => {\n count += data.length\n\t\t\tdb.collection('sensor_event')\n .insertMany(data, { ordered: false, writeConcern: { w: 0 } })\n .catch(err => err.code === 11000 ? {} : console.dir(err))\n console.dir([pID, count, Date.now(), process.memoryUsage()])\n callback(null, null)\n\t\t}))\n .on('end', () => {\n console.log(`ANALYTICS complete!`)\n })\n}\nasync function check(db, collection) {\n console.log(`${collection} = ${await db.collection(collection).estimatedDocumentCount()} docs`)\n //console.log(JSON.stringify((await nano.use(collection).list()).rows.map(x => x.id).sort()))\n //console.log(JSON.stringify((await db.collection(collection).find({}, { _id: 1 }).toArray()).map(x => x._id).sort()))\n}\nasync function fixup(db) {\n await db.collection('researcher').remove({_id: {$regex: /^_design.*/}})\n await db.collection('study').remove({_id: {$regex: /^_design.*/}})\n await db.collection('participant').remove({_id: {$regex: /^_design.*/}})\n await db.collection('activity').remove({_id: {$regex: /^_design.*/}})\n await db.collection('sensor').remove({_id: {$regex: /^_design.*/}})\n await db.collection('activity_spec').remove({_id: {$regex: /^_design.*/}})\n await db.collection('sensor_spec').remove({_id: {$regex: /^_design.*/}})\n await db.collection('tag').remove({_id: {$regex: /^_design.*/}})\n await db.collection('credential').remove({_id: {$regex: /^_design.*/}})\n \n // THIS WILL BE INCREDIBLY SLOW SINCE WE DO NOT USE INDEXES FOR THESE:\n //await db.collection('activity_event').remove({_id: {$regex: /^_design.*/}})\n //await db.collection('sensor_event').remove({_id: {$regex: /^_design.*/}})\n}\n\n// FIXME: DO NOT USE THIS; THIS IS A BACKUP ONLY!\nasync function _migrate_old_deprecated() {\n await MongoClient.connect()\n const db = await MongoClient.db('LAMP_staging').collection('sensor_event')\n nano.use('sensor_event')\n .listAsStream({ include_docs: true })\n .on('error', (e) => console.error('error', e))\n .pipe(JSONStream.parse('rows.*.doc'))\n .pipe(es.mapSync(x => {\n let transformed = [{\n _deleted: false,\n _parent: x['#parent'],\n timestamp: x.timestamp,\n sensor: x.sensor,\n data: x.data\n }]\n db.insertMany(transformed).catch(err => err.code === 11000 ? {} : console.dir(err))\n }))\n}\n\nasync function migrate(db, collection, skip, startkey) {\n console.log(`${collection} start = ${await db.collection(collection).estimatedDocumentCount()}`)\n let count = skip || 0\n\tnano.use(collection)\n\t\t.listAsStream({ startkey: startkey, include_docs: true })\n\t\t.on('error', (e) => console.error('error', e))\n\t\t.pipe(JSONStream.parse(['rows', /./, 'doc']))\n .pipe(es.map((data, callback) => {\n data._deleted = false\n data._parent = data['#parent']\n delete data._rev\n delete data['#parent']\n if (collection === \"tag\") // HARDCODED FOR TAG ONLY!\n data.value = JSON.stringify(data.value)\n callback(null, data)\n }))\n .pipe(through2batch.obj({ batchSize: 100000 }))\n\t\t.pipe(es.map((data, callback) => {\n count += data.length\n\t\t\tdb.collection(collection)\n .insertMany(data, { ordered: false, writeConcern: { w: 0 }})\n .catch(err => console.dir(err))\n console.dir([data.slice(-1)[0]._id, count, Date.now(), process.memoryUsage()])\n callback(null, null)\n\t\t}))\n .on('end', async () => {\n console.log(`${collection} complete = ${await db.collection(collection).estimatedDocumentCount()} docs!`)\n console.log('PLEASE KEEP THIS TERMINAL SESSION OPEN UNTIL MONGODB HAS LOADED ALL CHANGES!')\n })\n}\n\nMongoClient.connect(MONGO_URL, { useUnifiedTopology: true }, async (err, client) => {\n const db = client.db(DB_NAME)\n \n // ONLY ONCE TO MAKE PUSH NOTIFICATIONS WORK CORRECTLY\n //for (let pID of ANALYTICS_IDS)\n // await migrateANALYTICS(db, pID)\n \n // FIXME: This also copies over CouchDB design documents, _id prefixed with \"_design/\".\n // USE BELOW LINE TO DELETE THEM FROM A COLLECTION\n //fixup(db)\n \n // CHECKING STATUS ONLY\n // USE ANOTHER TERMINAL WINDOW TO QUERY PROGRESS WITH A COPY \n // OF THIS SCRIPT WITH `check(...)` UNCOMMENTED!\n //check(db, 'tag')\n \n // YOU CAN ONLY RUN ONE AT A TIME:\n //migrate(db, 'researcher')\n //migrate(db, 'study')\n //migrate(db, 'participant')\n //migrate(db, 'activity')\n //migrate(db, 'sensor')\n //migrate(db, 'activity_event')\n //migrate(db, 'tag')\n //migrate(db, 'credential')\n //migrate(db, 'activity_spec')\n //migrate(db, 'sensor_spec')\n migrate(db, 'sensor_event', undefined, undefined)\n})\n"})}),"\n",(0,a.jsx)(n.p,{children:"You will likely need to adjust Node options to run the script."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"export node_options=--max_old_space_size=14000\n# set to around ~80% of max limit (default of 2GB WILL FAIL)\n"})}),"\n",(0,a.jsxs)(n.p,{children:["To automate installation of prerequisite packages, use this ",(0,a.jsx)(n.code,{children:"package.json"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",metastring:'title="package.json"',children:'{\n "name": "couch_mongo_importer",\n "version": "1.0.0",\n "main": "index.js",\n "scripts": {\n "start": "node index.js"\n },\n "dependencies": {\n "event-stream": "^4.0.1",\n "JSONStream": "^1.3.5",\n "mongodb": "^3.6.6",\n "nano": "^9.0.3",\n "through2-batch": "^1.1.1"\n }\n}\n'})})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},28453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>c});var o=t(96540);const a={},i=o.createContext(a);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2041],{4133:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"develop/couchdb-migration","title":"Migrating from CouchDB to MongoDB","description":"Please carefully read and replace the variables in this JS script before continuing:","source":"@site/docs/08-develop/11-couchdb-migration.md","sourceDirName":"08-develop","slug":"/develop/couchdb-migration","permalink":"/develop/couchdb-migration","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/08-develop/11-couchdb-migration.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":11,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"OAuth2/OIDC Support","permalink":"/develop/oauth_oidc"},"next":{"title":"Training Modules","permalink":"/develop/Training Modules/training-modules"}}');var a=t(74848),i=t(28453);const r={},c="Migrating from CouchDB to MongoDB",s={},d=[];function l(e){const n={code:"code",h1:"h1",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"migrating-from-couchdb-to-mongodb",children:"Migrating from CouchDB to MongoDB"})}),"\n",(0,a.jsx)(n.p,{children:"Please carefully read and replace the variables in this JS script before continuing:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",metastring:'title="index.js"',children:"#!/usr/bin/env node\nconst es = require('event-stream')\nconst JSONStream = require('JSONStream')\nconst through2batch = require('through2-batch')\n//const nano = require('nano')('http://admin:REDACTED_PASSWORD@10.0.0.1:5984/') // STAGING\nconst nano = require('nano')('http://admin:REDACTED_PASSWORD@10.0.0.2:5984/') // PRODUCTION\nconst { MongoClient } = require('mongodb')\nconst MONGO_URL = 'mongodb://USERNAME_REDACTED:PASSWORD_REDACTED@CLUSTER_NAME_REDACTED.us-east-2.docdb.amazonaws.com:27017/LAMP?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false'\nconst DB_NAME = \"LAMP\"\n\n// MAKE THE REQUIRED COLLECTIONS AND INDEXES FIRST BEFORE LOADING DATA IN! \n/*\nconst REQUIRED_INDEXES = {\n \"researcher\": [\n { timestamp: 1 }, \n { timestamp: 1, _id: 1 }\n ],\n \"study\": [\n { timestamp: 1 }, \n { timestamp: 1, _id: 1 }, \n { timestamp: 1, _id: 1, _parent: 1 }\n ],\n \"participant\": [\n { timestamp: 1 }, \n { _parent: 1, timestamp: 1 }, \n { _id: 1, _parent: 1, timestamp: 1 }\n ],\n \"activity\": [\n { timestamp: 1 },\n { timestamp: 1, _parent: 1 },\n { _id: 1, timestamp: 1 },\n { timestamp: 1, _id: 1, _parent: 1 },\n ],\n \"sensor\": [\n { timestamp: 1 },\n { timestamp: 1, _parent: 1 },\n { _id: 1, timestamp: 1 },\n { timestamp: 1, _id: 1, _parent: 1 },\n ],\n \"activity_event\": [\n { _parent: -1, activity: -1, timestamp: -1 },\n { _parent: -1, timestamp: -1 },\n ],\n \"tag\": [\n { _parent: 1, type: 1, key: 1 }\n ],\n \"credential\": [\n { access_key: 1 }, \n { origin: 1 }, \n { origin: 1, access_key: 1 }\n ],\n \"sensor_event\": [\n { _parent: -1, sensor: -1, timestamp: -1 },\n { _parent: -1, timestamp: -1 },\n ],\n}\nfor (let [collection, indexes] of Object.entries(REQUIRED_INDEXES)) {\n console.dir([collection, indexes])\n db.collection(collection).createIndexes(indexes).catch(err => console.dir(err))\n}\n*/\n\n// IGNORE THIS, SEE BELOW INSTEAD\nconst ANALYTICS_IDS = []\nasync function migrateANALYTICS(db, pID) {\n let count = 0\n\tnano.use('sensor_event')\n\t\t.findAsStream({\n selector: {\n \"#parent\": pID,\n \"sensor\": \"lamp.analytics\",\n },\n sort: [{ timestamp: 'desc' }],\n limit: 100000\n })\n\t\t.on('error', (e) => console.error('error', e))\n\t\t.pipe(JSONStream.parse('docs.*'))\n .pipe(es.map((data, callback) => {\n data._deleted = false\n data._parent = data['#parent']\n delete data._rev\n delete data['#parent']\n callback(null, data)\n }))\n .pipe(through2batch.obj({ batchSize: 100000 }))\n\t\t.pipe(es.map((data, callback) => {\n count += data.length\n\t\t\tdb.collection('sensor_event')\n .insertMany(data, { ordered: false, writeConcern: { w: 0 } })\n .catch(err => err.code === 11000 ? {} : console.dir(err))\n console.dir([pID, count, Date.now(), process.memoryUsage()])\n callback(null, null)\n\t\t}))\n .on('end', () => {\n console.log(`ANALYTICS complete!`)\n })\n}\nasync function check(db, collection) {\n console.log(`${collection} = ${await db.collection(collection).estimatedDocumentCount()} docs`)\n //console.log(JSON.stringify((await nano.use(collection).list()).rows.map(x => x.id).sort()))\n //console.log(JSON.stringify((await db.collection(collection).find({}, { _id: 1 }).toArray()).map(x => x._id).sort()))\n}\nasync function fixup(db) {\n await db.collection('researcher').remove({_id: {$regex: /^_design.*/}})\n await db.collection('study').remove({_id: {$regex: /^_design.*/}})\n await db.collection('participant').remove({_id: {$regex: /^_design.*/}})\n await db.collection('activity').remove({_id: {$regex: /^_design.*/}})\n await db.collection('sensor').remove({_id: {$regex: /^_design.*/}})\n await db.collection('activity_spec').remove({_id: {$regex: /^_design.*/}})\n await db.collection('sensor_spec').remove({_id: {$regex: /^_design.*/}})\n await db.collection('tag').remove({_id: {$regex: /^_design.*/}})\n await db.collection('credential').remove({_id: {$regex: /^_design.*/}})\n \n // THIS WILL BE INCREDIBLY SLOW SINCE WE DO NOT USE INDEXES FOR THESE:\n //await db.collection('activity_event').remove({_id: {$regex: /^_design.*/}})\n //await db.collection('sensor_event').remove({_id: {$regex: /^_design.*/}})\n}\n\n// FIXME: DO NOT USE THIS; THIS IS A BACKUP ONLY!\nasync function _migrate_old_deprecated() {\n await MongoClient.connect()\n const db = await MongoClient.db('LAMP_staging').collection('sensor_event')\n nano.use('sensor_event')\n .listAsStream({ include_docs: true })\n .on('error', (e) => console.error('error', e))\n .pipe(JSONStream.parse('rows.*.doc'))\n .pipe(es.mapSync(x => {\n let transformed = [{\n _deleted: false,\n _parent: x['#parent'],\n timestamp: x.timestamp,\n sensor: x.sensor,\n data: x.data\n }]\n db.insertMany(transformed).catch(err => err.code === 11000 ? {} : console.dir(err))\n }))\n}\n\nasync function migrate(db, collection, skip, startkey) {\n console.log(`${collection} start = ${await db.collection(collection).estimatedDocumentCount()}`)\n let count = skip || 0\n\tnano.use(collection)\n\t\t.listAsStream({ startkey: startkey, include_docs: true })\n\t\t.on('error', (e) => console.error('error', e))\n\t\t.pipe(JSONStream.parse(['rows', /./, 'doc']))\n .pipe(es.map((data, callback) => {\n data._deleted = false\n data._parent = data['#parent']\n delete data._rev\n delete data['#parent']\n if (collection === \"tag\") // HARDCODED FOR TAG ONLY!\n data.value = JSON.stringify(data.value)\n callback(null, data)\n }))\n .pipe(through2batch.obj({ batchSize: 100000 }))\n\t\t.pipe(es.map((data, callback) => {\n count += data.length\n\t\t\tdb.collection(collection)\n .insertMany(data, { ordered: false, writeConcern: { w: 0 }})\n .catch(err => console.dir(err))\n console.dir([data.slice(-1)[0]._id, count, Date.now(), process.memoryUsage()])\n callback(null, null)\n\t\t}))\n .on('end', async () => {\n console.log(`${collection} complete = ${await db.collection(collection).estimatedDocumentCount()} docs!`)\n console.log('PLEASE KEEP THIS TERMINAL SESSION OPEN UNTIL MONGODB HAS LOADED ALL CHANGES!')\n })\n}\n\nMongoClient.connect(MONGO_URL, { useUnifiedTopology: true }, async (err, client) => {\n const db = client.db(DB_NAME)\n \n // ONLY ONCE TO MAKE PUSH NOTIFICATIONS WORK CORRECTLY\n //for (let pID of ANALYTICS_IDS)\n // await migrateANALYTICS(db, pID)\n \n // FIXME: This also copies over CouchDB design documents, _id prefixed with \"_design/\".\n // USE BELOW LINE TO DELETE THEM FROM A COLLECTION\n //fixup(db)\n \n // CHECKING STATUS ONLY\n // USE ANOTHER TERMINAL WINDOW TO QUERY PROGRESS WITH A COPY \n // OF THIS SCRIPT WITH `check(...)` UNCOMMENTED!\n //check(db, 'tag')\n \n // YOU CAN ONLY RUN ONE AT A TIME:\n //migrate(db, 'researcher')\n //migrate(db, 'study')\n //migrate(db, 'participant')\n //migrate(db, 'activity')\n //migrate(db, 'sensor')\n //migrate(db, 'activity_event')\n //migrate(db, 'tag')\n //migrate(db, 'credential')\n //migrate(db, 'activity_spec')\n //migrate(db, 'sensor_spec')\n migrate(db, 'sensor_event', undefined, undefined)\n})\n"})}),"\n",(0,a.jsx)(n.p,{children:"You will likely need to adjust Node options to run the script."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"export node_options=--max_old_space_size=14000\n# set to around ~80% of max limit (default of 2GB WILL FAIL)\n"})}),"\n",(0,a.jsxs)(n.p,{children:["To automate installation of prerequisite packages, use this ",(0,a.jsx)(n.code,{children:"package.json"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",metastring:'title="package.json"',children:'{\n "name": "couch_mongo_importer",\n "version": "1.0.0",\n "main": "index.js",\n "scripts": {\n "start": "node index.js"\n },\n "dependencies": {\n "event-stream": "^4.0.1",\n "JSONStream": "^1.3.5",\n "mongodb": "^3.6.6",\n "nano": "^9.0.3",\n "through2-batch": "^1.1.1"\n }\n}\n'})})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},28453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>c});var o=t(96540);const a={},i=o.createContext(a);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/01672fa2.436a5fa0.js b/assets/js/01672fa2.7400e58f.js similarity index 99% rename from assets/js/01672fa2.436a5fa0.js rename to assets/js/01672fa2.7400e58f.js index b0201367c1..7e1773bde4 100644 --- a/assets/js/01672fa2.436a5fa0.js +++ b/assets/js/01672fa2.7400e58f.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4622],{43719:(e,a,s)=>{s.r(a),s.d(a,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>n,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"data_science/cortex/visualizations/basic_analysis","title":"Basic Analysis","description":"There are some basic analyses that are useful for exploring study data. The Jupyter Notebook cortex/visualizations/correlation_plots.ipynb has code to:","source":"@site/docs/09-data_science/06-cortex/06-visualizations/02-basic_analysis.md","sourceDirName":"09-data_science/06-cortex/06-visualizations","slug":"/data_science/cortex/visualizations/basic_analysis","permalink":"/data_science/cortex/visualizations/basic_analysis","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/06-visualizations/02-basic_analysis.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":2,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Data Quality","permalink":"/data_science/cortex/visualizations/data_quality"},"next":{"title":"Participant-Level Visualizations","permalink":"/data_science/cortex/visualizations/participant_level"}}');var i=s(74848),r=s(28453);const n={},o="Basic Analysis",l={},c=[{value:"Data",id:"data",level:3},{value:"Survey data",id:"survey-data",level:4},{value:"Passive data",id:"passive-data",level:4},{value:"Other features",id:"other-features",level:4},{value:"Analysis",id:"analysis",level:3},{value:"Correlations",id:"correlations",level:4},{value:"Comparison across groups",id:"comparison-across-groups",level:4},{value:"Logistic regression model",id:"logistic-regression-model",level:4}];function d(e){const a={h1:"h1",h3:"h3",h4:"h4",header:"header",img:"img",li:"li",ol:"ol",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(a.header,{children:(0,i.jsx)(a.h1,{id:"basic-analysis",children:"Basic Analysis"})}),"\n",(0,i.jsx)(a.p,{children:"There are some basic analyses that are useful for exploring study data. The Jupyter Notebook cortex/visualizations/correlation_plots.ipynb has code to:"}),"\n",(0,i.jsxs)(a.ol,{children:["\n",(0,i.jsx)(a.li,{children:"Score survey data and save it into a user specified directory."}),"\n",(0,i.jsx)(a.li,{children:"Load survey data, passive data features, and any other researcher-generated features to generate correlation plots."}),"\n",(0,i.jsx)(a.li,{children:"Compare features across groups of interest."}),"\n",(0,i.jsx)(a.li,{children:"Fit a basic logistic regression model to predict the participants group based on the features."}),"\n"]}),"\n",(0,i.jsx)(a.p,{children:"While these functionalities are by no means comprehensive, they can provide a starting place for further exploration."}),"\n",(0,i.jsx)(a.h3,{id:"data",children:"Data"}),"\n",(0,i.jsx)(a.h4,{id:"survey-data",children:"Survey data"}),"\n",(0,i.jsx)(a.p,{children:"Surveys are scored using Cortex's score_surveys() function. Results are saved by survey category by participant in individual csv files. Each csv file will have a column for the timestamp as well as columns for each question in the survey and a total score."}),"\n",(0,i.jsx)(a.h4,{id:"passive-data",children:"Passive data"}),"\n",(0,i.jsx)(a.p,{children:"Passive data should be processed prior to analysis. cortex.run() can be used to generate the file format required. In particular, secondary features should be in pickle files with a column for timestamp and a column for the value of the secondary feature."}),"\n",(0,i.jsx)(a.h4,{id:"other-features",children:"Other features"}),"\n",(0,i.jsx)(a.p,{children:'Additional data can come in the form of "global" data or data that holds true across the entirety of the study (ex: number of activities, age). These features should be stored in a csv file called participantId_other_global_features.csv where each column of the dataframe is a differnet global feature. Each column that you would like to be used in analysis should be listed in the list OTHER_GLOBAL_FEATS.'}),"\n",(0,i.jsx)(a.p,{children:'Other local features are "local" in time. These features look just like survey or passive data in that they will have a timestamp column (in ms) as well as columns for each feature. The file can be named anything, and the name of the file may or may not be in the columns. Using this filename, files will be saved in SURVEY_DIR as participantID_filename.csv. OTHER_LOCAL_FEATS should be a list of all of these file names. Then you must specify which columns in each file that should be usef in analysis. An example of how to do this in OTHER_LOCAL_SUBFEATS is shown below.'}),"\n",(0,i.jsx)(a.h3,{id:"analysis",children:"Analysis"}),"\n",(0,i.jsx)(a.p,{children:"For example, we could look at GAD-7 questions, sleep duration, and some passive data features from one of our studies. These example features are listed below."}),"\n",(0,i.jsx)(a.p,{children:(0,i.jsx)(a.img,{src:s(26998).A+"",width:"442",height:"244"})}),"\n",(0,i.jsx)(a.h4,{id:"correlations",children:"Correlations"}),"\n",(0,i.jsx)(a.p,{children:"Using these features, we could then produce a correlation map. The * indicate signficant correlations (p < 0.05, corrected for multiple comparisons)."}),"\n",(0,i.jsx)(a.p,{children:(0,i.jsx)(a.img,{src:s(44881).A+"",width:"1320",height:"1409"})}),"\n",(0,i.jsx)(a.h4,{id:"comparison-across-groups",children:"Comparison across groups"}),"\n",(0,i.jsx)(a.p,{children:"We could then look at whether these features differed among participants that improved over the course of the study. Significantly different groups based on a t-test (p < 0.05, corrected for multiple comparisons) are marked with *. Entropy, home time, and GPS data quality differ between the group that did and did not improve."}),"\n",(0,i.jsx)(a.p,{children:(0,i.jsx)(a.img,{src:s(23831).A+"",width:"722",height:"712"})}),"\n",(0,i.jsx)(a.h4,{id:"logistic-regression-model",children:"Logistic regression model"}),"\n",(0,i.jsx)(a.p,{children:"Finally, we fit a logistic regression model to predict which participants improved. The model achieved an AUC of 0.862 and had three non-zero coefficients:"}),"\n",(0,i.jsxs)(a.table,{children:[(0,i.jsx)(a.thead,{children:(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.th,{children:"Feature"}),(0,i.jsx)(a.th,{children:"Coefficient"})]})}),(0,i.jsxs)(a.tbody,{children:[(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.td,{children:"entropy"}),(0,i.jsx)(a.td,{children:"0.468"})]}),(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.td,{children:"screen_duration"}),(0,i.jsx)(a.td,{children:"0.212"})]}),(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.td,{children:"sleep_duration"}),(0,i.jsx)(a.td,{children:"0.223"})]})]})]}),"\n",(0,i.jsx)(a.p,{children:"From here, we can take a deeper look at why some features may be different across groups or investigate the relationships between correlated variables. The goal of these visualizations is to provide a starting point for further analysis."})]})}function h(e={}){const{wrapper:a}={...(0,r.R)(),...e.components};return a?(0,i.jsx)(a,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},23831:(e,a,s)=>{s.d(a,{A:()=>t});const t=s.p+"assets/images/comp_feats-a7a5519327c7069a6196a7e7a15565fe.png"},44881:(e,a,s)=>{s.d(a,{A:()=>t});const t=s.p+"assets/images/corr_example-d4c0b8af34386d4e82b07f52ea56c270.png"},26998:(e,a,s)=>{s.d(a,{A:()=>t});const t=s.p+"assets/images/corr_key-976b0f6d56c508bb260ba52e313c05b2.png"},28453:(e,a,s)=>{s.d(a,{R:()=>n,x:()=>o});var t=s(96540);const i={},r=t.createContext(i);function n(e){const a=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:n(e.components),t.createElement(r.Provider,{value:a},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4622],{43719:(e,a,s)=>{s.r(a),s.d(a,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>n,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"data_science/cortex/visualizations/basic_analysis","title":"Basic Analysis","description":"There are some basic analyses that are useful for exploring study data. The Jupyter Notebook cortex/visualizations/correlation_plots.ipynb has code to:","source":"@site/docs/09-data_science/06-cortex/06-visualizations/02-basic_analysis.md","sourceDirName":"09-data_science/06-cortex/06-visualizations","slug":"/data_science/cortex/visualizations/basic_analysis","permalink":"/data_science/cortex/visualizations/basic_analysis","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/06-visualizations/02-basic_analysis.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":2,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Data Quality","permalink":"/data_science/cortex/visualizations/data_quality"},"next":{"title":"Participant-Level Visualizations","permalink":"/data_science/cortex/visualizations/participant_level"}}');var i=s(74848),r=s(28453);const n={},o="Basic Analysis",l={},c=[{value:"Data",id:"data",level:3},{value:"Survey data",id:"survey-data",level:4},{value:"Passive data",id:"passive-data",level:4},{value:"Other features",id:"other-features",level:4},{value:"Analysis",id:"analysis",level:3},{value:"Correlations",id:"correlations",level:4},{value:"Comparison across groups",id:"comparison-across-groups",level:4},{value:"Logistic regression model",id:"logistic-regression-model",level:4}];function d(e){const a={h1:"h1",h3:"h3",h4:"h4",header:"header",img:"img",li:"li",ol:"ol",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(a.header,{children:(0,i.jsx)(a.h1,{id:"basic-analysis",children:"Basic Analysis"})}),"\n",(0,i.jsx)(a.p,{children:"There are some basic analyses that are useful for exploring study data. The Jupyter Notebook cortex/visualizations/correlation_plots.ipynb has code to:"}),"\n",(0,i.jsxs)(a.ol,{children:["\n",(0,i.jsx)(a.li,{children:"Score survey data and save it into a user specified directory."}),"\n",(0,i.jsx)(a.li,{children:"Load survey data, passive data features, and any other researcher-generated features to generate correlation plots."}),"\n",(0,i.jsx)(a.li,{children:"Compare features across groups of interest."}),"\n",(0,i.jsx)(a.li,{children:"Fit a basic logistic regression model to predict the participants group based on the features."}),"\n"]}),"\n",(0,i.jsx)(a.p,{children:"While these functionalities are by no means comprehensive, they can provide a starting place for further exploration."}),"\n",(0,i.jsx)(a.h3,{id:"data",children:"Data"}),"\n",(0,i.jsx)(a.h4,{id:"survey-data",children:"Survey data"}),"\n",(0,i.jsx)(a.p,{children:"Surveys are scored using Cortex's score_surveys() function. Results are saved by survey category by participant in individual csv files. Each csv file will have a column for the timestamp as well as columns for each question in the survey and a total score."}),"\n",(0,i.jsx)(a.h4,{id:"passive-data",children:"Passive data"}),"\n",(0,i.jsx)(a.p,{children:"Passive data should be processed prior to analysis. cortex.run() can be used to generate the file format required. In particular, secondary features should be in pickle files with a column for timestamp and a column for the value of the secondary feature."}),"\n",(0,i.jsx)(a.h4,{id:"other-features",children:"Other features"}),"\n",(0,i.jsx)(a.p,{children:'Additional data can come in the form of "global" data or data that holds true across the entirety of the study (ex: number of activities, age). These features should be stored in a csv file called participantId_other_global_features.csv where each column of the dataframe is a differnet global feature. Each column that you would like to be used in analysis should be listed in the list OTHER_GLOBAL_FEATS.'}),"\n",(0,i.jsx)(a.p,{children:'Other local features are "local" in time. These features look just like survey or passive data in that they will have a timestamp column (in ms) as well as columns for each feature. The file can be named anything, and the name of the file may or may not be in the columns. Using this filename, files will be saved in SURVEY_DIR as participantID_filename.csv. OTHER_LOCAL_FEATS should be a list of all of these file names. Then you must specify which columns in each file that should be usef in analysis. An example of how to do this in OTHER_LOCAL_SUBFEATS is shown below.'}),"\n",(0,i.jsx)(a.h3,{id:"analysis",children:"Analysis"}),"\n",(0,i.jsx)(a.p,{children:"For example, we could look at GAD-7 questions, sleep duration, and some passive data features from one of our studies. These example features are listed below."}),"\n",(0,i.jsx)(a.p,{children:(0,i.jsx)(a.img,{src:s(26998).A+"",width:"442",height:"244"})}),"\n",(0,i.jsx)(a.h4,{id:"correlations",children:"Correlations"}),"\n",(0,i.jsx)(a.p,{children:"Using these features, we could then produce a correlation map. The * indicate signficant correlations (p < 0.05, corrected for multiple comparisons)."}),"\n",(0,i.jsx)(a.p,{children:(0,i.jsx)(a.img,{src:s(44881).A+"",width:"1320",height:"1409"})}),"\n",(0,i.jsx)(a.h4,{id:"comparison-across-groups",children:"Comparison across groups"}),"\n",(0,i.jsx)(a.p,{children:"We could then look at whether these features differed among participants that improved over the course of the study. Significantly different groups based on a t-test (p < 0.05, corrected for multiple comparisons) are marked with *. Entropy, home time, and GPS data quality differ between the group that did and did not improve."}),"\n",(0,i.jsx)(a.p,{children:(0,i.jsx)(a.img,{src:s(23831).A+"",width:"722",height:"712"})}),"\n",(0,i.jsx)(a.h4,{id:"logistic-regression-model",children:"Logistic regression model"}),"\n",(0,i.jsx)(a.p,{children:"Finally, we fit a logistic regression model to predict which participants improved. The model achieved an AUC of 0.862 and had three non-zero coefficients:"}),"\n",(0,i.jsxs)(a.table,{children:[(0,i.jsx)(a.thead,{children:(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.th,{children:"Feature"}),(0,i.jsx)(a.th,{children:"Coefficient"})]})}),(0,i.jsxs)(a.tbody,{children:[(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.td,{children:"entropy"}),(0,i.jsx)(a.td,{children:"0.468"})]}),(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.td,{children:"screen_duration"}),(0,i.jsx)(a.td,{children:"0.212"})]}),(0,i.jsxs)(a.tr,{children:[(0,i.jsx)(a.td,{children:"sleep_duration"}),(0,i.jsx)(a.td,{children:"0.223"})]})]})]}),"\n",(0,i.jsx)(a.p,{children:"From here, we can take a deeper look at why some features may be different across groups or investigate the relationships between correlated variables. The goal of these visualizations is to provide a starting point for further analysis."})]})}function h(e={}){const{wrapper:a}={...(0,r.R)(),...e.components};return a?(0,i.jsx)(a,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},23831:(e,a,s)=>{s.d(a,{A:()=>t});const t=s.p+"assets/images/comp_feats-a7a5519327c7069a6196a7e7a15565fe.png"},44881:(e,a,s)=>{s.d(a,{A:()=>t});const t=s.p+"assets/images/corr_example-d4c0b8af34386d4e82b07f52ea56c270.png"},26998:(e,a,s)=>{s.d(a,{A:()=>t});const t=s.p+"assets/images/corr_key-976b0f6d56c508bb260ba52e313c05b2.png"},28453:(e,a,s)=>{s.d(a,{R:()=>n,x:()=>o});var t=s(96540);const i={},r=t.createContext(i);function n(e){const a=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:n(e.components),t.createElement(r.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/03018b92.9c47a251.js b/assets/js/03018b92.bd22db79.js similarity index 96% rename from assets/js/03018b92.9c47a251.js rename to assets/js/03018b92.bd22db79.js index 5394e045f1..a8b23f5a01 100644 --- a/assets/js/03018b92.9c47a251.js +++ b/assets/js/03018b92.bd22db79.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[734],{19889:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>u,default:()=>l,frontMatter:()=>i,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"quick_links/bug","title":"Report issues","description":"If you encounter any issues with the app, please check out our community forum//mindlamp.discourse.group/","source":"@site/docs/02-quick_links/02-bug.md","sourceDirName":"02-quick_links","slug":"/bug","permalink":"/bug","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/02-quick_links/02-bug.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":2,"frontMatter":{"slug":"/bug"},"sidebar":"defaultSidebar","previous":{"title":"Download mindLAMP","permalink":"/app"},"next":{"title":"Frequently Asked Questions","permalink":"/faq"}}');var r=s(74848),o=s(28453);const i={slug:"/bug"},u="Report issues",a={},c=[];function p(e){const t={a:"a",h1:"h1",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"report-issues",children:"Report issues"})}),"\n",(0,r.jsxs)(t.p,{children:["If you encounter any issues with the app, please check out our community forum: ",(0,r.jsx)(t.a,{href:"https://mindlamp.discourse.group/",children:"https://mindlamp.discourse.group/"})]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},28453:(e,t,s)=>{s.d(t,{R:()=>i,x:()=>u});var n=s(96540);const r={},o=n.createContext(r);function i(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[734],{19889:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>u,default:()=>l,frontMatter:()=>i,metadata:()=>n,toc:()=>c});const n=JSON.parse('{"id":"quick_links/bug","title":"Report issues","description":"If you encounter any issues with the app, please check out our community forum//mindlamp.discourse.group/","source":"@site/docs/02-quick_links/02-bug.md","sourceDirName":"02-quick_links","slug":"/bug","permalink":"/bug","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/02-quick_links/02-bug.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":2,"frontMatter":{"slug":"/bug"},"sidebar":"defaultSidebar","previous":{"title":"Download mindLAMP","permalink":"/app"},"next":{"title":"Frequently Asked Questions","permalink":"/faq"}}');var r=s(74848),o=s(28453);const i={slug:"/bug"},u="Report issues",a={},c=[];function p(e){const t={a:"a",h1:"h1",header:"header",p:"p",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"report-issues",children:"Report issues"})}),"\n",(0,r.jsxs)(t.p,{children:["If you encounter any issues with the app, please check out our community forum: ",(0,r.jsx)(t.a,{href:"https://mindlamp.discourse.group/",children:"https://mindlamp.discourse.group/"})]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},28453:(e,t,s)=>{s.d(t,{R:()=>i,x:()=>u});var n=s(96540);const r={},o=n.createContext(r);function i(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/04a65cf0.0ac87472.js b/assets/js/04a65cf0.7d67cc4c.js similarity index 99% rename from assets/js/04a65cf0.0ac87472.js rename to assets/js/04a65cf0.7d67cc4c.js index 18695395fc..7624ebf9d4 100644 --- a/assets/js/04a65cf0.0ac87472.js +++ b/assets/js/04a65cf0.7d67cc4c.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[3372],{25055:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>c,frontMatter:()=>o,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"quick_links/faq","title":"Frequently Asked Questions","description":"Why are there two mindLAMP apps available? Which one should I use?","source":"@site/docs/02-quick_links/03-faq.md","sourceDirName":"02-quick_links","slug":"/faq","permalink":"/faq","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/02-quick_links/03-faq.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":3,"frontMatter":{"slug":"/faq"},"sidebar":"defaultSidebar","previous":{"title":"Report issues","permalink":"/bug"},"next":{"title":"Security & Privacy Policy","permalink":"/privacy"}}');var n=a(74848),s=a(28453);const o={slug:"/faq"},r="Frequently Asked Questions",d={},l=[{value:"Why are there two mindLAMP apps available? Which one should I use?",id:"why-are-there-two-mindlamp-apps-available-which-one-should-i-use",level:3},{value:"How do I transition from mindLAMP 1 to mindLAMP 2?",id:"how-do-i-transition-from-mindlamp-1-to-mindlamp-2",level:3},{value:"Do I need a wearable to collect passive data?",id:"do-i-need-a-wearable-to-collect-passive-data",level:3},{value:"What can I customize to my study or clinic?",id:"what-can-i-customize-to-my-study-or-clinic",level:3},{value:"What's a system administrator?",id:"whats-a-system-administrator",level:3},{value:"How do I get login information?",id:"how-do-i-get-login-information",level:3},{value:"How do I reset my password?",id:"how-do-i-reset-my-password",level:3},{value:"What's a study?",id:"whats-a-study",level:3},{value:"What's the difference between a survey and an activity?",id:"whats-the-difference-between-a-survey-and-an-activity",level:3},{value:"How do I create a survey?",id:"how-do-i-create-a-survey",level:3},{value:"Can I edit a survey?",id:"can-i-edit-a-survey",level:3},{value:"What happens to my data after I delete a survey?",id:"what-happens-to-my-data-after-i-delete-a-survey",level:3},{value:"How do I delete a survey?",id:"how-do-i-delete-a-survey",level:3},{value:"How do I customize an activity?",id:"how-do-i-customize-an-activity",level:3},{value:"There aren't any surveys or activities in my Feed. Why?",id:"there-arent-any-surveys-or-activities-in-my-feed-why",level:3},{value:"Why is my Manage section appearing blank?",id:"why-is-my-manage-section-appearing-blank",level:3},{value:"Who can see my data?",id:"who-can-see-my-data",level:3},{value:"Does the mindLAMP app work offline?",id:"does-the-mindlamp-app-work-offline",level:3},{value:"Where do I report a bug or request a feature?",id:"where-do-i-report-a-bug-or-request-a-feature",level:3},{value:"Is mindLAMP 2 available in other languages?",id:"is-mindlamp-2-available-in-other-languages",level:3},{value:"Is there a page for quick troubleshooting?",id:"is-there-a-page-for-quick-troubleshooting",level:3}];function h(e){const t={a:"a",code:"code",h1:"h1",h3:"h3",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"frequently-asked-questions",children:"Frequently Asked Questions"})}),"\n",(0,n.jsx)(t.h3,{id:"why-are-there-two-mindlamp-apps-available-which-one-should-i-use",children:"Why are there two mindLAMP apps available? Which one should I use?"}),"\n",(0,n.jsx)(t.p,{children:"The app that is associated with the LAMP Platform is called mindLAMP. mindLAMP 1 is no longer being used and has been replaced by mindLAMP 2. You will no longer be able to download or use the mindLAMP 1 app in early 2021."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-transition-from-mindlamp-1-to-mindlamp-2",children:"How do I transition from mindLAMP 1 to mindLAMP 2?"}),"\n",(0,n.jsx)(t.p,{children:"If you are using mindLAMP with a web browser like Chrome, Safari, Firefox etc. then it will automatically have updated. If you are using the app, simply download mindLAMP 2 from the App Store or Play Store and log in."}),"\n",(0,n.jsx)(t.h3,{id:"do-i-need-a-wearable-to-collect-passive-data",children:"Do I need a wearable to collect passive data?"}),"\n",(0,n.jsx)(t.p,{children:"HealthKit data is only available with wearables with two exceptions: step count and sleep data. Step count can be gathered through your mobile device, and sleep data can be gathered by downloading specific apps on iOS (napbot) and Android (sleep as android). mindLAMP requires WatchOS 7 and WearOS 2."}),"\n",(0,n.jsx)(t.h3,{id:"what-can-i-customize-to-my-study-or-clinic",children:"What can I customize to my study or clinic?"}),"\n",(0,n.jsx)(t.p,{children:"You are able to customize tips in Learn, surveys in Assess, activities in Assess and Manage, and potentially visualizations in Prevent."}),"\n",(0,n.jsx)(t.h3,{id:"whats-a-system-administrator",children:"What's a system administrator?"}),"\n",(0,n.jsx)(t.p,{children:"This is usually your Information Technology (IT) or Information Services (IS) department at your institution."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-get-login-information",children:"How do I get login information?"}),"\n",(0,n.jsxs)(t.p,{children:["If you or your organization is self-hosting the LAMP Platform independently, please contact your administrator or IT department for your login information; ",(0,n.jsx)(t.a,{href:"mailto:team@digitalpsych.org",children:"otherwise, please contact us."})]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-reset-my-password",children:"How do I reset my password?"}),"\n",(0,n.jsx)(t.p,{children:"If you are a study participant, please reach out to your research coordinator. If you are a patient, please reach out to your clinician. If you are a research coordinator or clinician, please reach out to your system administrator or IT department."}),"\n",(0,n.jsx)(t.h3,{id:"whats-a-study",children:"What's a study?"}),"\n",(0,n.jsx)(t.p,{children:"A study comprises of a set of activities that multiple patients will interact with and receive notifications for, such as surveys or breathing exercises, as well as a set of sensors which will be enabled to collect data on the patients' smartphones or wearable devices. Researchers and clinicians add able to create and manage multiple studies."}),"\n",(0,n.jsx)(t.h3,{id:"whats-the-difference-between-a-survey-and-an-activity",children:"What's the difference between a survey and an activity?"}),"\n",(0,n.jsx)(t.p,{children:'"Activity" is a broad term that encompasses different items that patients can interact with inside of the mindLAMP app. This includes cognitive tests, mindfulness, meditation, and more. A survey is a type of activity that presents a set of questions for patients or participants to answer.'}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-create-a-survey",children:"How do I create a survey?"}),"\n",(0,n.jsxs)(t.p,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"}),' button at the top right of the list and select "Survey Instrument".']}),"\n",(0,n.jsx)(t.h3,{id:"can-i-edit-a-survey",children:"Can I edit a survey?"}),"\n",(0,n.jsx)(t.p,{children:"Yes, you can edit it from the activities tab by tapping on its row in the list. We recommend only editing surveys to fix typos or adjust the language of a question or response choice."}),"\n",(0,n.jsx)(t.h3,{id:"what-happens-to-my-data-after-i-delete-a-survey",children:"What happens to my data after I delete a survey?"}),"\n",(0,n.jsx)(t.p,{children:"Deleting a survey or other activity automatically deletes their response data across all participants or patients. This data is always recoverable \u2014 please reach out to your system administrator for help recovering data."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-delete-a-survey",children:"How do I delete a survey?"}),"\n",(0,n.jsx)(t.p,{children:"Select one or more survey instruments you would like to delete and press the trash can icon at the top right of the list."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-customize-an-activity",children:"How do I customize an activity?"}),"\n",(0,n.jsxs)(t.p,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list and select your desired activity. All customization options for a specific activity will be on the screen that follows."]}),"\n",(0,n.jsx)(t.h3,{id:"there-arent-any-surveys-or-activities-in-my-feed-why",children:"There aren't any surveys or activities in my Feed. Why?"}),"\n",(0,n.jsx)(t.p,{children:"You may need to set schedules for the surveys or activities that you have assigned to your study. Please make sure you're viewing the Feed on a day where one of those schedules is activated to send notifications."}),"\n",(0,n.jsx)(t.h3,{id:"why-is-my-manage-section-appearing-blank",children:"Why is my Manage section appearing blank?"}),"\n",(0,n.jsx)(t.p,{children:"You must add activities for them to show up in a specific tab. If there are no activities created for a specific tab, that tab will remain blank."}),"\n",(0,n.jsx)(t.h3,{id:"who-can-see-my-data",children:"Who can see my data?"}),"\n",(0,n.jsx)(t.p,{children:"Your system administrator will only access your personal information to support internal operations, including troubleshooting/user support, and service improvements. To ensure you are receiving the highest level of service in your interaction with the mindLAMP app, the Division of Digital Psychiatry may use your contact information to communicate with you regarding your requests.\xa0We also use this data to create aggregated statistics which helps us in the improvement of our service."}),"\n",(0,n.jsx)(t.h3,{id:"does-the-mindlamp-app-work-offline",children:"Does the mindLAMP app work offline?"}),"\n",(0,n.jsx)(t.p,{children:"The mindLAMP app does not currently work offline. However, this is a highly requested feature that we are working on."}),"\n",(0,n.jsx)(t.h3,{id:"where-do-i-report-a-bug-or-request-a-feature",children:"Where do I report a bug or request a feature?"}),"\n",(0,n.jsxs)(t.p,{children:["Submit any bugs or feature requests here: ",(0,n.jsx)(t.a,{href:"/bug",children:"Report a Bug or Request a Feature"})]}),"\n",(0,n.jsx)(t.h3,{id:"is-mindlamp-2-available-in-other-languages",children:"Is mindLAMP 2 available in other languages?"}),"\n",(0,n.jsx)(t.p,{children:"In addition to English, the mindLAMP app currently supports Chinese (Simplified and Traditional), Danish, French, German, Hindi, Italian, Korean, and Spanish."}),"\n",(0,n.jsx)(t.h3,{id:"is-there-a-page-for-quick-troubleshooting",children:"Is there a page for quick troubleshooting?"}),"\n",(0,n.jsxs)(t.p,{children:["If you require immediate advice on how to solve some commonly encountered issues, please see the ",(0,n.jsx)(t.a,{href:"https://docs.lamp.digital/troubleshooting",children:"Troubleshooting Page"})]})]})}function c(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},28453:(e,t,a)=>{a.d(t,{R:()=>o,x:()=>r});var i=a(96540);const n={},s=i.createContext(n);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[3372],{25055:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>c,frontMatter:()=>o,metadata:()=>i,toc:()=>l});const i=JSON.parse('{"id":"quick_links/faq","title":"Frequently Asked Questions","description":"Why are there two mindLAMP apps available? Which one should I use?","source":"@site/docs/02-quick_links/03-faq.md","sourceDirName":"02-quick_links","slug":"/faq","permalink":"/faq","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/02-quick_links/03-faq.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":3,"frontMatter":{"slug":"/faq"},"sidebar":"defaultSidebar","previous":{"title":"Report issues","permalink":"/bug"},"next":{"title":"Security & Privacy Policy","permalink":"/privacy"}}');var n=a(74848),s=a(28453);const o={slug:"/faq"},r="Frequently Asked Questions",d={},l=[{value:"Why are there two mindLAMP apps available? Which one should I use?",id:"why-are-there-two-mindlamp-apps-available-which-one-should-i-use",level:3},{value:"How do I transition from mindLAMP 1 to mindLAMP 2?",id:"how-do-i-transition-from-mindlamp-1-to-mindlamp-2",level:3},{value:"Do I need a wearable to collect passive data?",id:"do-i-need-a-wearable-to-collect-passive-data",level:3},{value:"What can I customize to my study or clinic?",id:"what-can-i-customize-to-my-study-or-clinic",level:3},{value:"What's a system administrator?",id:"whats-a-system-administrator",level:3},{value:"How do I get login information?",id:"how-do-i-get-login-information",level:3},{value:"How do I reset my password?",id:"how-do-i-reset-my-password",level:3},{value:"What's a study?",id:"whats-a-study",level:3},{value:"What's the difference between a survey and an activity?",id:"whats-the-difference-between-a-survey-and-an-activity",level:3},{value:"How do I create a survey?",id:"how-do-i-create-a-survey",level:3},{value:"Can I edit a survey?",id:"can-i-edit-a-survey",level:3},{value:"What happens to my data after I delete a survey?",id:"what-happens-to-my-data-after-i-delete-a-survey",level:3},{value:"How do I delete a survey?",id:"how-do-i-delete-a-survey",level:3},{value:"How do I customize an activity?",id:"how-do-i-customize-an-activity",level:3},{value:"There aren't any surveys or activities in my Feed. Why?",id:"there-arent-any-surveys-or-activities-in-my-feed-why",level:3},{value:"Why is my Manage section appearing blank?",id:"why-is-my-manage-section-appearing-blank",level:3},{value:"Who can see my data?",id:"who-can-see-my-data",level:3},{value:"Does the mindLAMP app work offline?",id:"does-the-mindlamp-app-work-offline",level:3},{value:"Where do I report a bug or request a feature?",id:"where-do-i-report-a-bug-or-request-a-feature",level:3},{value:"Is mindLAMP 2 available in other languages?",id:"is-mindlamp-2-available-in-other-languages",level:3},{value:"Is there a page for quick troubleshooting?",id:"is-there-a-page-for-quick-troubleshooting",level:3}];function h(e){const t={a:"a",code:"code",h1:"h1",h3:"h3",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"frequently-asked-questions",children:"Frequently Asked Questions"})}),"\n",(0,n.jsx)(t.h3,{id:"why-are-there-two-mindlamp-apps-available-which-one-should-i-use",children:"Why are there two mindLAMP apps available? Which one should I use?"}),"\n",(0,n.jsx)(t.p,{children:"The app that is associated with the LAMP Platform is called mindLAMP. mindLAMP 1 is no longer being used and has been replaced by mindLAMP 2. You will no longer be able to download or use the mindLAMP 1 app in early 2021."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-transition-from-mindlamp-1-to-mindlamp-2",children:"How do I transition from mindLAMP 1 to mindLAMP 2?"}),"\n",(0,n.jsx)(t.p,{children:"If you are using mindLAMP with a web browser like Chrome, Safari, Firefox etc. then it will automatically have updated. If you are using the app, simply download mindLAMP 2 from the App Store or Play Store and log in."}),"\n",(0,n.jsx)(t.h3,{id:"do-i-need-a-wearable-to-collect-passive-data",children:"Do I need a wearable to collect passive data?"}),"\n",(0,n.jsx)(t.p,{children:"HealthKit data is only available with wearables with two exceptions: step count and sleep data. Step count can be gathered through your mobile device, and sleep data can be gathered by downloading specific apps on iOS (napbot) and Android (sleep as android). mindLAMP requires WatchOS 7 and WearOS 2."}),"\n",(0,n.jsx)(t.h3,{id:"what-can-i-customize-to-my-study-or-clinic",children:"What can I customize to my study or clinic?"}),"\n",(0,n.jsx)(t.p,{children:"You are able to customize tips in Learn, surveys in Assess, activities in Assess and Manage, and potentially visualizations in Prevent."}),"\n",(0,n.jsx)(t.h3,{id:"whats-a-system-administrator",children:"What's a system administrator?"}),"\n",(0,n.jsx)(t.p,{children:"This is usually your Information Technology (IT) or Information Services (IS) department at your institution."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-get-login-information",children:"How do I get login information?"}),"\n",(0,n.jsxs)(t.p,{children:["If you or your organization is self-hosting the LAMP Platform independently, please contact your administrator or IT department for your login information; ",(0,n.jsx)(t.a,{href:"mailto:team@digitalpsych.org",children:"otherwise, please contact us."})]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-reset-my-password",children:"How do I reset my password?"}),"\n",(0,n.jsx)(t.p,{children:"If you are a study participant, please reach out to your research coordinator. If you are a patient, please reach out to your clinician. If you are a research coordinator or clinician, please reach out to your system administrator or IT department."}),"\n",(0,n.jsx)(t.h3,{id:"whats-a-study",children:"What's a study?"}),"\n",(0,n.jsx)(t.p,{children:"A study comprises of a set of activities that multiple patients will interact with and receive notifications for, such as surveys or breathing exercises, as well as a set of sensors which will be enabled to collect data on the patients' smartphones or wearable devices. Researchers and clinicians add able to create and manage multiple studies."}),"\n",(0,n.jsx)(t.h3,{id:"whats-the-difference-between-a-survey-and-an-activity",children:"What's the difference between a survey and an activity?"}),"\n",(0,n.jsx)(t.p,{children:'"Activity" is a broad term that encompasses different items that patients can interact with inside of the mindLAMP app. This includes cognitive tests, mindfulness, meditation, and more. A survey is a type of activity that presents a set of questions for patients or participants to answer.'}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-create-a-survey",children:"How do I create a survey?"}),"\n",(0,n.jsxs)(t.p,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"}),' button at the top right of the list and select "Survey Instrument".']}),"\n",(0,n.jsx)(t.h3,{id:"can-i-edit-a-survey",children:"Can I edit a survey?"}),"\n",(0,n.jsx)(t.p,{children:"Yes, you can edit it from the activities tab by tapping on its row in the list. We recommend only editing surveys to fix typos or adjust the language of a question or response choice."}),"\n",(0,n.jsx)(t.h3,{id:"what-happens-to-my-data-after-i-delete-a-survey",children:"What happens to my data after I delete a survey?"}),"\n",(0,n.jsx)(t.p,{children:"Deleting a survey or other activity automatically deletes their response data across all participants or patients. This data is always recoverable \u2014 please reach out to your system administrator for help recovering data."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-delete-a-survey",children:"How do I delete a survey?"}),"\n",(0,n.jsx)(t.p,{children:"Select one or more survey instruments you would like to delete and press the trash can icon at the top right of the list."}),"\n",(0,n.jsx)(t.h3,{id:"how-do-i-customize-an-activity",children:"How do I customize an activity?"}),"\n",(0,n.jsxs)(t.p,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list and select your desired activity. All customization options for a specific activity will be on the screen that follows."]}),"\n",(0,n.jsx)(t.h3,{id:"there-arent-any-surveys-or-activities-in-my-feed-why",children:"There aren't any surveys or activities in my Feed. Why?"}),"\n",(0,n.jsx)(t.p,{children:"You may need to set schedules for the surveys or activities that you have assigned to your study. Please make sure you're viewing the Feed on a day where one of those schedules is activated to send notifications."}),"\n",(0,n.jsx)(t.h3,{id:"why-is-my-manage-section-appearing-blank",children:"Why is my Manage section appearing blank?"}),"\n",(0,n.jsx)(t.p,{children:"You must add activities for them to show up in a specific tab. If there are no activities created for a specific tab, that tab will remain blank."}),"\n",(0,n.jsx)(t.h3,{id:"who-can-see-my-data",children:"Who can see my data?"}),"\n",(0,n.jsx)(t.p,{children:"Your system administrator will only access your personal information to support internal operations, including troubleshooting/user support, and service improvements. To ensure you are receiving the highest level of service in your interaction with the mindLAMP app, the Division of Digital Psychiatry may use your contact information to communicate with you regarding your requests.\xa0We also use this data to create aggregated statistics which helps us in the improvement of our service."}),"\n",(0,n.jsx)(t.h3,{id:"does-the-mindlamp-app-work-offline",children:"Does the mindLAMP app work offline?"}),"\n",(0,n.jsx)(t.p,{children:"The mindLAMP app does not currently work offline. However, this is a highly requested feature that we are working on."}),"\n",(0,n.jsx)(t.h3,{id:"where-do-i-report-a-bug-or-request-a-feature",children:"Where do I report a bug or request a feature?"}),"\n",(0,n.jsxs)(t.p,{children:["Submit any bugs or feature requests here: ",(0,n.jsx)(t.a,{href:"/bug",children:"Report a Bug or Request a Feature"})]}),"\n",(0,n.jsx)(t.h3,{id:"is-mindlamp-2-available-in-other-languages",children:"Is mindLAMP 2 available in other languages?"}),"\n",(0,n.jsx)(t.p,{children:"In addition to English, the mindLAMP app currently supports Chinese (Simplified and Traditional), Danish, French, German, Hindi, Italian, Korean, and Spanish."}),"\n",(0,n.jsx)(t.h3,{id:"is-there-a-page-for-quick-troubleshooting",children:"Is there a page for quick troubleshooting?"}),"\n",(0,n.jsxs)(t.p,{children:["If you require immediate advice on how to solve some commonly encountered issues, please see the ",(0,n.jsx)(t.a,{href:"https://docs.lamp.digital/troubleshooting",children:"Troubleshooting Page"})]})]})}function c(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},28453:(e,t,a)=>{a.d(t,{R:()=>o,x:()=>r});var i=a(96540);const n={},s=i.createContext(n);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/05cd1bee.29a42988.js b/assets/js/05cd1bee.a924e2f4.js similarity index 98% rename from assets/js/05cd1bee.29a42988.js rename to assets/js/05cd1bee.a924e2f4.js index e4172603f6..6c8ec323a3 100644 --- a/assets/js/05cd1bee.29a42988.js +++ b/assets/js/05cd1bee.a924e2f4.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2500],{72388:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});const a=JSON.parse('{"id":"start_here/battery_data_usage","title":"Checking LAMP battery and data usage","description":"Though LAMP is designed to be lightweight and use low amounts of data and battery life, users who wish to see how LAMP uses data and battery life on their device may do so by one of the following device-dependent methods.","source":"@site/docs/06-start_here/14-battery_data_usage.md","sourceDirName":"06-start_here","slug":"/start_here/battery_data_usage","permalink":"/start_here/battery_data_usage","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/14-battery_data_usage.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":14,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"LAMP Updates Tutorial","permalink":"/start_here/updates_tutorial"},"next":{"title":"Modifying the frequency of a sensor\'s data collection","permalink":"/start_here/updating_frequency"}}');var s=n(74848),i=n(28453);const r={},o="Checking LAMP battery and data usage",l={},d=[];function c(e){const t={h1:"h1",header:"header",li:"li",ol:"ol",p:"p",...(0,i.R)(),...e.components},{Details:n}=t;return n||function(e,t){throw new Error("Expected "+(t?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"checking-lamp-battery-and-data-usage",children:"Checking LAMP battery and data usage"})}),"\n",(0,s.jsx)(t.p,{children:"Though LAMP is designed to be lightweight and use low amounts of data and battery life, users who wish to see how LAMP uses data and battery life on their device may do so by one of the following device-dependent methods."}),"\n",(0,s.jsxs)(n,{children:[(0,s.jsx)("summary",{children:"iOS Devices"}),(0,s.jsx)("b",{children:"Battery Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Open the 'Settings' app."}),"\n",(0,s.jsx)(t.li,{children:"In the sidebar on the left-hand side, find and click on the 'Battery' tab."}),"\n",(0,s.jsx)(t.li,{children:"Scroll down the 'Battery' page until you see the 'Activity by App' entry, then tap on 'Show Battery Usage' to show percent of battery used by each app on your device."}),"\n",(0,s.jsx)(t.li,{children:"Scroll down the list to locate the LAMP app"}),"\n"]}),(0,s.jsx)("b",{children:"Data Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Open the 'Settings' app."}),"\n",(0,s.jsx)(t.li,{children:"In the sidebar on the left-hand side, find and click on the 'Cellular' tab."}),"\n",(0,s.jsx)(t.li,{children:"Scroll down the list to locate the LAMP app and view its data usage."}),"\n"]})]}),"\n",(0,s.jsxs)(n,{children:[(0,s.jsx)("summary",{children:"Android Devices"}),(0,s.jsx)("b",{children:"Battery Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"Open the 'Settings' app."}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"Scroll down to and click on 'Battery'."}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"Click on 'View Detailed Usage' and scroll down the list to locate the LAMP app."}),"\n"]}),"\n"]}),(0,s.jsx)("b",{children:"Data Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Open the 'Settings' app."}),"\n",(0,s.jsx)(t.li,{children:"Click on 'Wi-Fi and internet'."}),"\n",(0,s.jsx)(t.li,{children:"Click on 'Data usage'."}),"\n",(0,s.jsx)(t.li,{children:"Click on 'Cellular data usage' and scroll to find the LAMP app."}),"\n"]})]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>o});var a=n(96540);const s={},i=a.createContext(s);function r(e){const t=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2500],{72388:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});const a=JSON.parse('{"id":"start_here/battery_data_usage","title":"Checking LAMP battery and data usage","description":"Though LAMP is designed to be lightweight and use low amounts of data and battery life, users who wish to see how LAMP uses data and battery life on their device may do so by one of the following device-dependent methods.","source":"@site/docs/06-start_here/14-battery_data_usage.md","sourceDirName":"06-start_here","slug":"/start_here/battery_data_usage","permalink":"/start_here/battery_data_usage","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/14-battery_data_usage.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":14,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"LAMP Updates Tutorial","permalink":"/start_here/updates_tutorial"},"next":{"title":"Modifying the frequency of a sensor\'s data collection","permalink":"/start_here/updating_frequency"}}');var s=n(74848),i=n(28453);const r={},o="Checking LAMP battery and data usage",l={},d=[];function c(e){const t={h1:"h1",header:"header",li:"li",ol:"ol",p:"p",...(0,i.R)(),...e.components},{Details:n}=t;return n||function(e,t){throw new Error("Expected "+(t?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"checking-lamp-battery-and-data-usage",children:"Checking LAMP battery and data usage"})}),"\n",(0,s.jsx)(t.p,{children:"Though LAMP is designed to be lightweight and use low amounts of data and battery life, users who wish to see how LAMP uses data and battery life on their device may do so by one of the following device-dependent methods."}),"\n",(0,s.jsxs)(n,{children:[(0,s.jsx)("summary",{children:"iOS Devices"}),(0,s.jsx)("b",{children:"Battery Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Open the 'Settings' app."}),"\n",(0,s.jsx)(t.li,{children:"In the sidebar on the left-hand side, find and click on the 'Battery' tab."}),"\n",(0,s.jsx)(t.li,{children:"Scroll down the 'Battery' page until you see the 'Activity by App' entry, then tap on 'Show Battery Usage' to show percent of battery used by each app on your device."}),"\n",(0,s.jsx)(t.li,{children:"Scroll down the list to locate the LAMP app"}),"\n"]}),(0,s.jsx)("b",{children:"Data Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Open the 'Settings' app."}),"\n",(0,s.jsx)(t.li,{children:"In the sidebar on the left-hand side, find and click on the 'Cellular' tab."}),"\n",(0,s.jsx)(t.li,{children:"Scroll down the list to locate the LAMP app and view its data usage."}),"\n"]})]}),"\n",(0,s.jsxs)(n,{children:[(0,s.jsx)("summary",{children:"Android Devices"}),(0,s.jsx)("b",{children:"Battery Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"Open the 'Settings' app."}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"Scroll down to and click on 'Battery'."}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"Click on 'View Detailed Usage' and scroll down the list to locate the LAMP app."}),"\n"]}),"\n"]}),(0,s.jsx)("b",{children:"Data Usage"}),(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Open the 'Settings' app."}),"\n",(0,s.jsx)(t.li,{children:"Click on 'Wi-Fi and internet'."}),"\n",(0,s.jsx)(t.li,{children:"Click on 'Data usage'."}),"\n",(0,s.jsx)(t.li,{children:"Click on 'Cellular data usage' and scroll to find the LAMP app."}),"\n"]})]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>o});var a=n(96540);const s={},i=a.createContext(s);function r(e){const t=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/05eb16d7.01823c8b.js b/assets/js/05eb16d7.fc56f9d2.js similarity index 98% rename from assets/js/05eb16d7.01823c8b.js rename to assets/js/05eb16d7.fc56f9d2.js index 8bb0470df3..5ac15ee540 100644 --- a/assets/js/05eb16d7.01823c8b.js +++ b/assets/js/05eb16d7.fc56f9d2.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4965],{92770:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"consortium/researcher/delete_user","title":"Delete a User or Share Login Link","description":"1. Log into the app and click on the \\"Users\\" tab.","source":"@site/docs/10-consortium/02-researcher/13-delete_user.md","sourceDirName":"10-consortium/02-researcher","slug":"/consortium/researcher/delete_user","permalink":"/consortium/researcher/delete_user","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/02-researcher/13-delete_user.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":13,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Reset a Patient\'s Credentials","permalink":"/consortium/researcher/reset_user"},"next":{"title":"Patient Checklist","permalink":"/consortium/patient/checklist"}}');var r=n(74848),i=n(28453);const o={},a="Delete a User or Share Login Link",c={},l=[];function d(e){const t={h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"delete-a-user-or-share-login-link",children:"Delete a User or Share Login Link"})}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,r.jsx)(t.li,{children:"Select one or more users by tapping the checkboxes at the left of their row."}),"\n",(0,r.jsx)(t.li,{children:"Tap the delete icon and confirm your selection."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(73583).A+"",width:"2360",height:"576"})}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.strong,{children:"All data associated with the patients/participants being deleted are irrecoverable and will be lost."})," Please exercise caution when deleting patients and confirm your selection to avoid permanent data loss."]}),"\n",(0,r.jsx)(t.h1,{id:"share-login",children:"Share Login"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(16943).A+"",width:"2358",height:"420"})}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,r.jsx)(t.li,{children:"Check the box next to the user's name."}),"\n",(0,r.jsxs)(t.li,{children:["Select the ",(0,r.jsx)(t.strong,{children:"Edit Password"})," option."]}),"\n",(0,r.jsx)(t.li,{children:"Click on the floopy disk icon and the QR code will appear underneath the text field."}),"\n",(0,r.jsx)(t.li,{children:"This is the login link you can send to users."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(73583).A+"",width:"2360",height:"576"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(8866).A+"",width:"1308",height:"1126"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},73583:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/edit_pass-63b22bcf02d50763d5dff29cd0d8a50b.jpg"},8866:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/share_qr-9deb49710737a69c0c2b06360baed8e3.jpg"},16943:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/users_tab-0e262569eb9e13f7ab30e02d75433857.jpg"},28453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(96540);const r={},i=s.createContext(r);function o(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4965],{92770:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"consortium/researcher/delete_user","title":"Delete a User or Share Login Link","description":"1. Log into the app and click on the \\"Users\\" tab.","source":"@site/docs/10-consortium/02-researcher/13-delete_user.md","sourceDirName":"10-consortium/02-researcher","slug":"/consortium/researcher/delete_user","permalink":"/consortium/researcher/delete_user","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/02-researcher/13-delete_user.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":13,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Reset a Patient\'s Credentials","permalink":"/consortium/researcher/reset_user"},"next":{"title":"Patient Checklist","permalink":"/consortium/patient/checklist"}}');var r=n(74848),i=n(28453);const o={},a="Delete a User or Share Login Link",c={},l=[];function d(e){const t={h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"delete-a-user-or-share-login-link",children:"Delete a User or Share Login Link"})}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,r.jsx)(t.li,{children:"Select one or more users by tapping the checkboxes at the left of their row."}),"\n",(0,r.jsx)(t.li,{children:"Tap the delete icon and confirm your selection."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(73583).A+"",width:"2360",height:"576"})}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.strong,{children:"All data associated with the patients/participants being deleted are irrecoverable and will be lost."})," Please exercise caution when deleting patients and confirm your selection to avoid permanent data loss."]}),"\n",(0,r.jsx)(t.h1,{id:"share-login",children:"Share Login"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(16943).A+"",width:"2358",height:"420"})}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,r.jsx)(t.li,{children:"Check the box next to the user's name."}),"\n",(0,r.jsxs)(t.li,{children:["Select the ",(0,r.jsx)(t.strong,{children:"Edit Password"})," option."]}),"\n",(0,r.jsx)(t.li,{children:"Click on the floopy disk icon and the QR code will appear underneath the text field."}),"\n",(0,r.jsx)(t.li,{children:"This is the login link you can send to users."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(73583).A+"",width:"2360",height:"576"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{src:n(8866).A+"",width:"1308",height:"1126"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},73583:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/edit_pass-63b22bcf02d50763d5dff29cd0d8a50b.jpg"},8866:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/share_qr-9deb49710737a69c0c2b06360baed8e3.jpg"},16943:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/users_tab-0e262569eb9e13f7ab30e02d75433857.jpg"},28453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(96540);const r={},i=s.createContext(r);function o(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/076d449a.82ef5761.js b/assets/js/076d449a.9a0b12a8.js similarity index 98% rename from assets/js/076d449a.82ef5761.js rename to assets/js/076d449a.9a0b12a8.js index c91b247673..0501a981ae 100644 --- a/assets/js/076d449a.82ef5761.js +++ b/assets/js/076d449a.9a0b12a8.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[104],{82781:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>n,toc:()=>o});const n=JSON.parse('{"id":"data_science/cortex/features/secondary/trip_distance","title":"Trip Distance","description":"computed from primary feature: cortex.primary.trips","source":"@site/docs/09-data_science/06-cortex/05-features/02-secondary/15-trip_distance.md","sourceDirName":"09-data_science/06-cortex/05-features/02-secondary","slug":"/data_science/cortex/features/secondary/trip_distance","permalink":"/data_science/cortex/features/secondary/trip_distance","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/05-features/02-secondary/15-trip_distance.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":15,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Survey Results","permalink":"/data_science/cortex/features/secondary/survey_results"},"next":{"title":"Trip Duration","permalink":"/data_science/cortex/features/secondary/trip_duration"}}');var i=r(74848),s=r(28453);const a={},c="Trip Distance",d={},o=[{value:"Description",id:"description",level:4},{value:"Optional or required kwargs",id:"optional-or-required-kwargs",level:4},{value:"Data",id:"data",level:4},{value:"Example",id:"example",level:4}];function l(e){const t={code:"code",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"trip-distance",children:"Trip Distance"})}),"\n",(0,i.jsxs)(t.p,{children:["computed from primary feature: ",(0,i.jsx)(t.code,{children:"cortex.primary.trips"}),"\ncomputed from raw feature: ",(0,i.jsx)(t.code,{children:"cortex.raw.gps"})]}),"\n",(0,i.jsx)(t.h4,{id:"description",children:"Description"}),"\n",(0,i.jsx)(t.p,{children:"Trip Distance is the total distance traveled on all trips in a period of time."}),"\n",(0,i.jsx)(t.h4,{id:"optional-or-required-kwargs",children:"Optional or required kwargs"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"start"}),": (int, units: ms) the start time."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"end"}),": (int, units: ms) the end time."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"resolution"}),": (int, units: ms) the resolution over which to compute features."]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"data",children:"Data"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"timestamp"}),": (int, units: ms) the start time of each bin of size ",(0,i.jsx)(t.code,{children:"kwargs['resolution']"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"value"}),": (float, units: km) the trip distance."]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:'cortex.secondary.trip_distance.trip_distance(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000)\n'})}),"\n",(0,i.jsx)(t.p,{children:"Output:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:"{\n 'timestamp': 0,\n 'duration': 5616000000,\n 'resolution': 86400000,\n 'data': [\n {'timestamp': 1607072400000, 'value': 0.018896610358911157},\n {'timestamp': 1607331600000, 'value': None},\n .\n .\n .\n {'timestamp': 1609232400000, 'value': 0.0228039384631051243}\n ]\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},28453:(e,t,r)=>{r.d(t,{R:()=>a,x:()=>c});var n=r(96540);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[104],{82781:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>n,toc:()=>o});const n=JSON.parse('{"id":"data_science/cortex/features/secondary/trip_distance","title":"Trip Distance","description":"computed from primary feature: cortex.primary.trips","source":"@site/docs/09-data_science/06-cortex/05-features/02-secondary/15-trip_distance.md","sourceDirName":"09-data_science/06-cortex/05-features/02-secondary","slug":"/data_science/cortex/features/secondary/trip_distance","permalink":"/data_science/cortex/features/secondary/trip_distance","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/05-features/02-secondary/15-trip_distance.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":15,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Survey Results","permalink":"/data_science/cortex/features/secondary/survey_results"},"next":{"title":"Trip Duration","permalink":"/data_science/cortex/features/secondary/trip_duration"}}');var i=r(74848),s=r(28453);const a={},c="Trip Distance",d={},o=[{value:"Description",id:"description",level:4},{value:"Optional or required kwargs",id:"optional-or-required-kwargs",level:4},{value:"Data",id:"data",level:4},{value:"Example",id:"example",level:4}];function l(e){const t={code:"code",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"trip-distance",children:"Trip Distance"})}),"\n",(0,i.jsxs)(t.p,{children:["computed from primary feature: ",(0,i.jsx)(t.code,{children:"cortex.primary.trips"}),"\ncomputed from raw feature: ",(0,i.jsx)(t.code,{children:"cortex.raw.gps"})]}),"\n",(0,i.jsx)(t.h4,{id:"description",children:"Description"}),"\n",(0,i.jsx)(t.p,{children:"Trip Distance is the total distance traveled on all trips in a period of time."}),"\n",(0,i.jsx)(t.h4,{id:"optional-or-required-kwargs",children:"Optional or required kwargs"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"start"}),": (int, units: ms) the start time."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"end"}),": (int, units: ms) the end time."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"resolution"}),": (int, units: ms) the resolution over which to compute features."]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"data",children:"Data"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"timestamp"}),": (int, units: ms) the start time of each bin of size ",(0,i.jsx)(t.code,{children:"kwargs['resolution']"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"value"}),": (float, units: km) the trip distance."]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:'cortex.secondary.trip_distance.trip_distance(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000)\n'})}),"\n",(0,i.jsx)(t.p,{children:"Output:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:"{\n 'timestamp': 0,\n 'duration': 5616000000,\n 'resolution': 86400000,\n 'data': [\n {'timestamp': 1607072400000, 'value': 0.018896610358911157},\n {'timestamp': 1607331600000, 'value': None},\n .\n .\n .\n {'timestamp': 1609232400000, 'value': 0.0228039384631051243}\n ]\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},28453:(e,t,r)=>{r.d(t,{R:()=>a,x:()=>c});var n=r(96540);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/085571f7.dfa5e6b9.js b/assets/js/085571f7.4dd13972.js similarity index 99% rename from assets/js/085571f7.dfa5e6b9.js rename to assets/js/085571f7.4dd13972.js index fc218771b0..94644db6e0 100644 --- a/assets/js/085571f7.dfa5e6b9.js +++ b/assets/js/085571f7.4dd13972.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[80],{24305:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"quick_links/privacy","title":"Security & Privacy Policy","description":"Your Personal Information","source":"@site/docs/02-quick_links/04-privacy.md","sourceDirName":"02-quick_links","slug":"/privacy","permalink":"/privacy","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/02-quick_links/04-privacy.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":4,"frontMatter":{"slug":"/privacy"},"sidebar":"defaultSidebar","previous":{"title":"Frequently Asked Questions","permalink":"/faq"},"next":{"title":"How does LAMP Platform Work?","permalink":"/about/intro"}}');var a=n(74848),r=n(28453);const o={slug:"/privacy"},s="Security & Privacy Policy",l={},d=[{value:"Your Personal Information",id:"your-personal-information",level:2},{value:"How We Use Your Personal Information",id:"how-we-use-your-personal-information",level:2},{value:"Google HealthConnect Data",id:"google-healthconnect-data",level:2},{value:"Information We Share With Others",id:"information-we-share-with-others",level:2},{value:"How We Protect Your Information",id:"how-we-protect-your-information",level:2},{value:"Deleting Your Account",id:"deleting-your-account",level:2},{value:"Can I delete data stored by the LAMP Platform?",id:"can-i-delete-data-stored-by-the-lamp-platform",level:3},{value:"Copyright And Proprietary Rights",id:"copyright-and-proprietary-rights",level:2},{value:"How do I let my IRB know that LAMP is safe to use in a research study?",id:"how-do-i-let-my-irb-know-that-lamp-is-safe-to-use-in-a-research-study",level:3},{value:"Security & Privacy",id:"security--privacy",level:2},{value:"Login and Authentication",id:"login-and-authentication",level:3},{value:"Technical Safeguards",id:"technical-safeguards",level:3},{value:"Personal Health Information (PHI)",id:"personal-health-information-phi",level:3},{value:"HIPAA",id:"hipaa",level:3},{value:"Breach Policy",id:"breach-policy",level:3},{value:"Risk Analysis and Management",id:"risk-analysis-and-management",level:3},{value:"Security Threat Protocol",id:"security-threat-protocol",level:3}];function c(e){const t={a:"a",blockquote:"blockquote",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"security--privacy-policy",children:"Security & Privacy Policy"})}),"\n",(0,a.jsx)(t.h2,{id:"your-personal-information",children:"Your Personal Information"}),"\n",(0,a.jsx)(t.p,{children:"\u201cYour information\u201d is the information we request when you initially download and launch the app. It is then accessible from your user profile under \u2018Settings.\u2019 This information includes, but is not limited to your user name and user profile you had used to register for the app. We also receive other types of information about you that is customarily gathered by web and mobile applications:"}),"\n",(0,a.jsx)(t.p,{children:"We receive data about you whenever you interact with the mindLAMP 2 app, such as when you launch the application, click on, view or otherwise interact with a feature. This may include date and time of the request, the feature requested, and completion status of the request. We receive data from the mobile phone you use to launch mindLAMP 2 app. We receive data about your answers to surveys and cognitive tests. If you opt in, we receive geospatial data that can tell us where you are nearby when you interact with the app. If you opt in, we receive data about your step count and other information provided by Apple Health Kit or Google HealthConnect."}),"\n",(0,a.jsx)(t.h2,{id:"how-we-use-your-personal-information",children:"How We Use Your Personal Information"}),"\n",(0,a.jsx)(t.p,{children:'Your personal information may be used to support internal operations, including troubleshooting/user support, and service improvements. To ensure you are receiving the highest level of service in your interaction with the mindLAMP 2 app, your contact information may be used to communicate back with you regarding your requests.\xa0We also use the data to create aggregated statistics which helps us in the improvement of our service. Aggregated data allows us to evaluate "traffic" patterns to our app in terms of the number and role of visitors, level of demand, most popular requests, and types of errors. These statistics are not linked to any personal information that can identify any individual person. This data may be kept for an indefinite amount of time, and it may also be used at any time and in any way reasonably necessary to monitor for security breaches and to ensure the integrity of the data on our servers.'}),"\n",(0,a.jsx)(t.p,{children:"The Division of Digital Psychiatry at the Beth Israel Deaconess Medical Center will never access your data without prior consent and permission. If self-deploying the LAMP Platform, you will be in sole control and ownership of all data consumed or produced by the LAMP platform. We do not by default request, use, or store any personally identifiable information, and strongly recommend against using the user-facing utilities to do so."}),"\n",(0,a.jsx)(t.h2,{id:"google-healthconnect-data",children:"Google HealthConnect Data"}),"\n",(0,a.jsx)(t.p,{children:"mindLAMP 2 has access to read information from the following Google HealthConnect sensors (though permission can be revoked for any individual sensor at the discretion of either the researcher or participant):"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Heart Rate"}),"\n",(0,a.jsx)(t.li,{children:"Steps"}),"\n",(0,a.jsx)(t.li,{children:"Speed"}),"\n",(0,a.jsx)(t.li,{children:"Calories Burned"}),"\n",(0,a.jsx)(t.li,{children:"Basal Metabolic Rate"}),"\n",(0,a.jsx)(t.li,{children:"Distance"}),"\n",(0,a.jsx)(t.li,{children:"Body Fat"}),"\n",(0,a.jsx)(t.li,{children:"Hydration"}),"\n",(0,a.jsx)(t.li,{children:"Nutrition"}),"\n",(0,a.jsx)(t.li,{children:"Blood Glucode"}),"\n",(0,a.jsx)(t.li,{children:"Blood Pressure"}),"\n",(0,a.jsx)(t.li,{children:"Oxygen Saturation"}),"\n",(0,a.jsx)(t.li,{children:"Body Temperature"}),"\n",(0,a.jsx)(t.li,{children:"Steps Cadence"}),"\n",(0,a.jsx)(t.li,{children:"Sleep"}),"\n",(0,a.jsx)(t.li,{children:"Respiratory Rate"}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"The use of information received from Health Connect will adhere to the Health Connect Permissions Policy, including the Limited Use requirements."}),"\n",(0,a.jsx)(t.h2,{id:"information-we-share-with-others",children:"Information We Share With Others"}),"\n",(0,a.jsx)(t.p,{children:"We do not sell, trade, or otherwise transfer to outside parties any information we receive. We may release information we collect to judicial, law enforcement or other government agencies when we believe release is appropriate to comply with a governmental or court order, or the law, to enforce our own policies, or to protect ours or others\u2019 rights, property or safety.\xa0We may share aggregate statistics about our visitors, general traffic patterns, app usage, survey answers, cognitive test results, and phone collected data like step count, geospatial location, flights of steps climbed (and other Apple Healthkit and Google HealthConnect data) for purely research purposes. If used for research, your data will be only used in an aggregate form. We will never use your data for marketing or commercial purposes."}),"\n",(0,a.jsx)(t.h2,{id:"how-we-protect-your-information",children:"How We Protect Your Information"}),"\n",(0,a.jsx)(t.p,{children:"We make every reasonable effort to protect your information against unauthorized access, alteration, disclosure or destruction using current security technologies. Servers that host the mindLAMP 2 app and store your personal information are maintained in a secured facility behind a firewall. The mindLAMP 2 app security measures are reviewed regularly and are consonant with policies for secure healthcare data storage. Finally, we restrict access to users\u2019 personal information to our employees, contractors and agents who need to know that information in order to process it on our behalf for purposes of providing you support and services. These individuals are required to attend training on patient privacy and confidentiality and are bound by strict confidentiality obligations."}),"\n",(0,a.jsx)(t.h2,{id:"deleting-your-account",children:"Deleting Your Account"}),"\n",(0,a.jsxs)(t.p,{children:["Your account may be deleted via the app through the delete my account button. You may delete your account at any time. You may also request to delete your account externally via the following Google form: ",(0,a.jsx)(t.a,{href:"https://forms.gle/rb7wSWgHBNwU1cQ78",children:"https://forms.gle/rb7wSWgHBNwU1cQ78"})]}),"\n",(0,a.jsx)(t.h3,{id:"can-i-delete-data-stored-by-the-lamp-platform",children:(0,a.jsx)(t.strong,{children:"Can I delete data stored by the LAMP Platform?"})}),"\n",(0,a.jsx)(t.p,{children:"Yes, you can delete any content stored in the LAMP Platform. There is a soft-deletion period of 90 days during which the data is unavailable but may be restored by request. Once the 90 day period ends, the data is deleted permanently, after which it may no longer be recovered."}),"\n",(0,a.jsx)(t.h2,{id:"copyright-and-proprietary-rights",children:"Copyright And Proprietary Rights"}),"\n",(0,a.jsx)(t.p,{children:"The mindLAMP 2 app, its features and contents are protected by copyright and other intellectual property laws, as well as other state, federal and international laws and regulations. Unless otherwise expressly provided in these Terms of Use, you may print or download information from the app for personal, non-commercial use only, provided you identify the source of the material, include a statement that the material is protected by copyright law, and do not modify any of the information. Reprinting, or otherwise reproducing, and/or reproducing any document in whole or in part is prohibited, unless prior written consent is obtained from the copyright owner."}),"\n",(0,a.jsx)(t.p,{children:"Nothing in these Terms of Use shall be deemed to grant you any right, title, license or interest in or to any software or documentation, or in any related patents, copyrights, trademarks, trade secrets or other intellectual property of any kind."}),"\n",(0,a.jsx)(t.h3,{id:"how-do-i-let-my-irb-know-that-lamp-is-safe-to-use-in-a-research-study",children:(0,a.jsx)(t.strong,{children:"How do I let my IRB know that LAMP is safe to use in a research study?"})}),"\n",(0,a.jsx)(t.p,{children:"Here's some language you might find useful in conveying the LAMP Platform's HIPAA compliance and safety to your IRB."}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsx)(t.p,{children:"Encrypted information from survey responses and passive data will be sent and stored electronically on a secure server. Responses from individual patients will be identified by a randomized number and contain no personal identifiable information apart from age and gender."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"Here's another example regarding participant anonymity."}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsx)(t.p,{children:"The app never records or stores any personal identity information. Every participant is assigned a randomly generated participant ID (for example, \u201cU123456789\u201d), and all participant data are connected only to that ID, not to a name, phone number, or address."}),"\n"]}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"security--privacy",children:"Security & Privacy"}),"\n",(0,a.jsx)(t.p,{children:"The LAMP Platform is free and open source software currently developed by Beth Israel Deaconess Medical Center but does not have any licensing restrictions for intellectual property. LAMP is safe, secure, and easy to use. Though it has broad potential, we will be using it as an interface that patients and clinicians can use together to track data and generate visual reports. It\u2019s important to note that LAMP is not an electronic health record system. Below is an outline of the technical specifications that back privacy and security in the LAMP Platform."}),"\n",(0,a.jsx)(t.h3,{id:"login-and-authentication",children:"Login and Authentication"}),"\n",(0,a.jsx)(t.p,{children:"Credentials are required to access the LAMP Platform. By default, a clinician can see the data of their patient, but any other access must be explicitly granted. The clinicians are able to view aggregate reports that contain no identifying information about the patients in the site."}),"\n",(0,a.jsx)(t.h3,{id:"technical-safeguards",children:"Technical Safeguards"}),"\n",(0,a.jsx)(t.p,{children:"As data is transferred between the device and server, it is encrypted in flight using the TLS v1.3 protocol atop the HTTP/2.0 transmission format. As data is accepted by the server, it is stored in the data lake encrypted at rest using AES-256 encryption through a secret key unique to each site. Any requests made to the server to create, update, delete, or even read data, will cause the incremental addition of the request to an audit log, along with the credentials used to make the request so it is possible for a site to monitor all requests for data."}),"\n",(0,a.jsx)(t.h3,{id:"personal-health-information-phi",children:"Personal Health Information (PHI)"}),"\n",(0,a.jsx)(t.p,{children:"There are 18 identifiers that make health information PHI. The one PHI type that LAMP will collect are dates as information is timestamped. LAMP will not collect patient names and uses codes instead. Thus, linking any information collected by LAMP to a unique patient is not easy without a key which will be kept by each site and not shared."}),"\n",(0,a.jsx)(t.h3,{id:"hipaa",children:"HIPAA"}),"\n",(0,a.jsx)(t.p,{children:"LAMP offers physical and technical safeguards that are in line with the HIPAA Security Privacy Rule. Specifically, the rule \u201crequires covered entities to maintain reasonable and appropriate administrative, technical, and physical safeguards for protecting e-PHI including:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Ensure the confidentiality, integrity, and availability of all e-PHI they create, receive, maintain or transmit;"}),"\n",(0,a.jsx)(t.li,{children:"Identify and protect against reasonably anticipated threats to the security or integrity of the information;"}),"\n",(0,a.jsx)(t.li,{children:"Protect against reasonably anticipated, impermissible uses or disclosures; and"}),"\n",(0,a.jsx)(t.li,{children:"Ensure compliance by their workforce."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.strong,{children:"LAMP meets this through the offering the follow features:"})}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Limited facility access and control with authorized access procedures in place"}),"\n",(0,a.jsx)(t.li,{children:"Restrictions for transferring, removing, disposing, and re-using PHI"}),"\n",(0,a.jsx)(t.li,{children:"Access control allowing only for authorized personnel to access PHI."}),"\n",(0,a.jsx)(t.li,{children:"Audit reports / tracking logs that record activity"}),"\n",(0,a.jsx)(t.li,{children:"Integrity controls in the database that ensure data is not altered or destroyed unless by an authorized user with the appropriate permissions"}),"\n",(0,a.jsx)(t.li,{children:"Encrypted network transmissions"}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"breach-policy",children:"Breach Policy"}),"\n",(0,a.jsx)(t.p,{children:"In the event of a suspected data breach, a site lead may immediately revoke all credentials and immediately disable access to the data. As both a public and private key are required to decrypt exported data, and separate private keys are maintained per site and per patient, a data breach of one sub-section of the data cannot and will not affect other sub-sections or the entire platform. Furthermore, devices are identified by a unique per-device token and data integrity in flight can be ensured when reviewing the audit trail by cross-referencing this device-specific token. As noted above, LAMP does not record name but identifies users by codes so even with a breach, it will be hard to connect a person to their data."}),"\n",(0,a.jsx)(t.h3,{id:"risk-analysis-and-management",children:"Risk Analysis and Management"}),"\n",(0,a.jsx)(t.p,{children:"Our team performs frequent risk analysis as part of our security management processes. We take the following steps to mitigate risk:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Daily review of logs for all BIDMC-hosted research and clinical sites to pinpoint potential risks."}),"\n",(0,a.jsx)(t.li,{children:"Determine the probability of a major security issue occuring."}),"\n",(0,a.jsx)(t.li,{children:"Frequent security updates to proactively prevent new threats to LAMP's security."}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"security-threat-protocol",children:"Security Threat Protocol"}),"\n",(0,a.jsx)(t.p,{children:"In the unlikely event of an active security threat, our team will take the following steps:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Determine how and what information has been endangered."}),"\n",(0,a.jsx)(t.li,{children:"Alert users with steps (if any) they must take, such as changing their passwords."}),"\n",(0,a.jsx)(t.li,{children:"Identify and complete the necessary steps our team must take to secure our server, dashboard, and data."}),"\n",(0,a.jsx)(t.li,{children:"Log the type of threat, when and how it occured, and the resolution."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>s});var i=n(96540);const a={},r=i.createContext(a);function o(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[80],{24305:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"quick_links/privacy","title":"Security & Privacy Policy","description":"Your Personal Information","source":"@site/docs/02-quick_links/04-privacy.md","sourceDirName":"02-quick_links","slug":"/privacy","permalink":"/privacy","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/02-quick_links/04-privacy.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":4,"frontMatter":{"slug":"/privacy"},"sidebar":"defaultSidebar","previous":{"title":"Frequently Asked Questions","permalink":"/faq"},"next":{"title":"How does LAMP Platform Work?","permalink":"/about/intro"}}');var a=n(74848),r=n(28453);const o={slug:"/privacy"},s="Security & Privacy Policy",l={},d=[{value:"Your Personal Information",id:"your-personal-information",level:2},{value:"How We Use Your Personal Information",id:"how-we-use-your-personal-information",level:2},{value:"Google HealthConnect Data",id:"google-healthconnect-data",level:2},{value:"Information We Share With Others",id:"information-we-share-with-others",level:2},{value:"How We Protect Your Information",id:"how-we-protect-your-information",level:2},{value:"Deleting Your Account",id:"deleting-your-account",level:2},{value:"Can I delete data stored by the LAMP Platform?",id:"can-i-delete-data-stored-by-the-lamp-platform",level:3},{value:"Copyright And Proprietary Rights",id:"copyright-and-proprietary-rights",level:2},{value:"How do I let my IRB know that LAMP is safe to use in a research study?",id:"how-do-i-let-my-irb-know-that-lamp-is-safe-to-use-in-a-research-study",level:3},{value:"Security & Privacy",id:"security--privacy",level:2},{value:"Login and Authentication",id:"login-and-authentication",level:3},{value:"Technical Safeguards",id:"technical-safeguards",level:3},{value:"Personal Health Information (PHI)",id:"personal-health-information-phi",level:3},{value:"HIPAA",id:"hipaa",level:3},{value:"Breach Policy",id:"breach-policy",level:3},{value:"Risk Analysis and Management",id:"risk-analysis-and-management",level:3},{value:"Security Threat Protocol",id:"security-threat-protocol",level:3}];function c(e){const t={a:"a",blockquote:"blockquote",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"security--privacy-policy",children:"Security & Privacy Policy"})}),"\n",(0,a.jsx)(t.h2,{id:"your-personal-information",children:"Your Personal Information"}),"\n",(0,a.jsx)(t.p,{children:"\u201cYour information\u201d is the information we request when you initially download and launch the app. It is then accessible from your user profile under \u2018Settings.\u2019 This information includes, but is not limited to your user name and user profile you had used to register for the app. We also receive other types of information about you that is customarily gathered by web and mobile applications:"}),"\n",(0,a.jsx)(t.p,{children:"We receive data about you whenever you interact with the mindLAMP 2 app, such as when you launch the application, click on, view or otherwise interact with a feature. This may include date and time of the request, the feature requested, and completion status of the request. We receive data from the mobile phone you use to launch mindLAMP 2 app. We receive data about your answers to surveys and cognitive tests. If you opt in, we receive geospatial data that can tell us where you are nearby when you interact with the app. If you opt in, we receive data about your step count and other information provided by Apple Health Kit or Google HealthConnect."}),"\n",(0,a.jsx)(t.h2,{id:"how-we-use-your-personal-information",children:"How We Use Your Personal Information"}),"\n",(0,a.jsx)(t.p,{children:'Your personal information may be used to support internal operations, including troubleshooting/user support, and service improvements. To ensure you are receiving the highest level of service in your interaction with the mindLAMP 2 app, your contact information may be used to communicate back with you regarding your requests.\xa0We also use the data to create aggregated statistics which helps us in the improvement of our service. Aggregated data allows us to evaluate "traffic" patterns to our app in terms of the number and role of visitors, level of demand, most popular requests, and types of errors. These statistics are not linked to any personal information that can identify any individual person. This data may be kept for an indefinite amount of time, and it may also be used at any time and in any way reasonably necessary to monitor for security breaches and to ensure the integrity of the data on our servers.'}),"\n",(0,a.jsx)(t.p,{children:"The Division of Digital Psychiatry at the Beth Israel Deaconess Medical Center will never access your data without prior consent and permission. If self-deploying the LAMP Platform, you will be in sole control and ownership of all data consumed or produced by the LAMP platform. We do not by default request, use, or store any personally identifiable information, and strongly recommend against using the user-facing utilities to do so."}),"\n",(0,a.jsx)(t.h2,{id:"google-healthconnect-data",children:"Google HealthConnect Data"}),"\n",(0,a.jsx)(t.p,{children:"mindLAMP 2 has access to read information from the following Google HealthConnect sensors (though permission can be revoked for any individual sensor at the discretion of either the researcher or participant):"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Heart Rate"}),"\n",(0,a.jsx)(t.li,{children:"Steps"}),"\n",(0,a.jsx)(t.li,{children:"Speed"}),"\n",(0,a.jsx)(t.li,{children:"Calories Burned"}),"\n",(0,a.jsx)(t.li,{children:"Basal Metabolic Rate"}),"\n",(0,a.jsx)(t.li,{children:"Distance"}),"\n",(0,a.jsx)(t.li,{children:"Body Fat"}),"\n",(0,a.jsx)(t.li,{children:"Hydration"}),"\n",(0,a.jsx)(t.li,{children:"Nutrition"}),"\n",(0,a.jsx)(t.li,{children:"Blood Glucode"}),"\n",(0,a.jsx)(t.li,{children:"Blood Pressure"}),"\n",(0,a.jsx)(t.li,{children:"Oxygen Saturation"}),"\n",(0,a.jsx)(t.li,{children:"Body Temperature"}),"\n",(0,a.jsx)(t.li,{children:"Steps Cadence"}),"\n",(0,a.jsx)(t.li,{children:"Sleep"}),"\n",(0,a.jsx)(t.li,{children:"Respiratory Rate"}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"The use of information received from Health Connect will adhere to the Health Connect Permissions Policy, including the Limited Use requirements."}),"\n",(0,a.jsx)(t.h2,{id:"information-we-share-with-others",children:"Information We Share With Others"}),"\n",(0,a.jsx)(t.p,{children:"We do not sell, trade, or otherwise transfer to outside parties any information we receive. We may release information we collect to judicial, law enforcement or other government agencies when we believe release is appropriate to comply with a governmental or court order, or the law, to enforce our own policies, or to protect ours or others\u2019 rights, property or safety.\xa0We may share aggregate statistics about our visitors, general traffic patterns, app usage, survey answers, cognitive test results, and phone collected data like step count, geospatial location, flights of steps climbed (and other Apple Healthkit and Google HealthConnect data) for purely research purposes. If used for research, your data will be only used in an aggregate form. We will never use your data for marketing or commercial purposes."}),"\n",(0,a.jsx)(t.h2,{id:"how-we-protect-your-information",children:"How We Protect Your Information"}),"\n",(0,a.jsx)(t.p,{children:"We make every reasonable effort to protect your information against unauthorized access, alteration, disclosure or destruction using current security technologies. Servers that host the mindLAMP 2 app and store your personal information are maintained in a secured facility behind a firewall. The mindLAMP 2 app security measures are reviewed regularly and are consonant with policies for secure healthcare data storage. Finally, we restrict access to users\u2019 personal information to our employees, contractors and agents who need to know that information in order to process it on our behalf for purposes of providing you support and services. These individuals are required to attend training on patient privacy and confidentiality and are bound by strict confidentiality obligations."}),"\n",(0,a.jsx)(t.h2,{id:"deleting-your-account",children:"Deleting Your Account"}),"\n",(0,a.jsxs)(t.p,{children:["Your account may be deleted via the app through the delete my account button. You may delete your account at any time. You may also request to delete your account externally via the following Google form: ",(0,a.jsx)(t.a,{href:"https://forms.gle/rb7wSWgHBNwU1cQ78",children:"https://forms.gle/rb7wSWgHBNwU1cQ78"})]}),"\n",(0,a.jsx)(t.h3,{id:"can-i-delete-data-stored-by-the-lamp-platform",children:(0,a.jsx)(t.strong,{children:"Can I delete data stored by the LAMP Platform?"})}),"\n",(0,a.jsx)(t.p,{children:"Yes, you can delete any content stored in the LAMP Platform. There is a soft-deletion period of 90 days during which the data is unavailable but may be restored by request. Once the 90 day period ends, the data is deleted permanently, after which it may no longer be recovered."}),"\n",(0,a.jsx)(t.h2,{id:"copyright-and-proprietary-rights",children:"Copyright And Proprietary Rights"}),"\n",(0,a.jsx)(t.p,{children:"The mindLAMP 2 app, its features and contents are protected by copyright and other intellectual property laws, as well as other state, federal and international laws and regulations. Unless otherwise expressly provided in these Terms of Use, you may print or download information from the app for personal, non-commercial use only, provided you identify the source of the material, include a statement that the material is protected by copyright law, and do not modify any of the information. Reprinting, or otherwise reproducing, and/or reproducing any document in whole or in part is prohibited, unless prior written consent is obtained from the copyright owner."}),"\n",(0,a.jsx)(t.p,{children:"Nothing in these Terms of Use shall be deemed to grant you any right, title, license or interest in or to any software or documentation, or in any related patents, copyrights, trademarks, trade secrets or other intellectual property of any kind."}),"\n",(0,a.jsx)(t.h3,{id:"how-do-i-let-my-irb-know-that-lamp-is-safe-to-use-in-a-research-study",children:(0,a.jsx)(t.strong,{children:"How do I let my IRB know that LAMP is safe to use in a research study?"})}),"\n",(0,a.jsx)(t.p,{children:"Here's some language you might find useful in conveying the LAMP Platform's HIPAA compliance and safety to your IRB."}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsx)(t.p,{children:"Encrypted information from survey responses and passive data will be sent and stored electronically on a secure server. Responses from individual patients will be identified by a randomized number and contain no personal identifiable information apart from age and gender."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"Here's another example regarding participant anonymity."}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsx)(t.p,{children:"The app never records or stores any personal identity information. Every participant is assigned a randomly generated participant ID (for example, \u201cU123456789\u201d), and all participant data are connected only to that ID, not to a name, phone number, or address."}),"\n"]}),"\n",(0,a.jsx)(t.hr,{}),"\n",(0,a.jsx)(t.h2,{id:"security--privacy",children:"Security & Privacy"}),"\n",(0,a.jsx)(t.p,{children:"The LAMP Platform is free and open source software currently developed by Beth Israel Deaconess Medical Center but does not have any licensing restrictions for intellectual property. LAMP is safe, secure, and easy to use. Though it has broad potential, we will be using it as an interface that patients and clinicians can use together to track data and generate visual reports. It\u2019s important to note that LAMP is not an electronic health record system. Below is an outline of the technical specifications that back privacy and security in the LAMP Platform."}),"\n",(0,a.jsx)(t.h3,{id:"login-and-authentication",children:"Login and Authentication"}),"\n",(0,a.jsx)(t.p,{children:"Credentials are required to access the LAMP Platform. By default, a clinician can see the data of their patient, but any other access must be explicitly granted. The clinicians are able to view aggregate reports that contain no identifying information about the patients in the site."}),"\n",(0,a.jsx)(t.h3,{id:"technical-safeguards",children:"Technical Safeguards"}),"\n",(0,a.jsx)(t.p,{children:"As data is transferred between the device and server, it is encrypted in flight using the TLS v1.3 protocol atop the HTTP/2.0 transmission format. As data is accepted by the server, it is stored in the data lake encrypted at rest using AES-256 encryption through a secret key unique to each site. Any requests made to the server to create, update, delete, or even read data, will cause the incremental addition of the request to an audit log, along with the credentials used to make the request so it is possible for a site to monitor all requests for data."}),"\n",(0,a.jsx)(t.h3,{id:"personal-health-information-phi",children:"Personal Health Information (PHI)"}),"\n",(0,a.jsx)(t.p,{children:"There are 18 identifiers that make health information PHI. The one PHI type that LAMP will collect are dates as information is timestamped. LAMP will not collect patient names and uses codes instead. Thus, linking any information collected by LAMP to a unique patient is not easy without a key which will be kept by each site and not shared."}),"\n",(0,a.jsx)(t.h3,{id:"hipaa",children:"HIPAA"}),"\n",(0,a.jsx)(t.p,{children:"LAMP offers physical and technical safeguards that are in line with the HIPAA Security Privacy Rule. Specifically, the rule \u201crequires covered entities to maintain reasonable and appropriate administrative, technical, and physical safeguards for protecting e-PHI including:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Ensure the confidentiality, integrity, and availability of all e-PHI they create, receive, maintain or transmit;"}),"\n",(0,a.jsx)(t.li,{children:"Identify and protect against reasonably anticipated threats to the security or integrity of the information;"}),"\n",(0,a.jsx)(t.li,{children:"Protect against reasonably anticipated, impermissible uses or disclosures; and"}),"\n",(0,a.jsx)(t.li,{children:"Ensure compliance by their workforce."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.strong,{children:"LAMP meets this through the offering the follow features:"})}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Limited facility access and control with authorized access procedures in place"}),"\n",(0,a.jsx)(t.li,{children:"Restrictions for transferring, removing, disposing, and re-using PHI"}),"\n",(0,a.jsx)(t.li,{children:"Access control allowing only for authorized personnel to access PHI."}),"\n",(0,a.jsx)(t.li,{children:"Audit reports / tracking logs that record activity"}),"\n",(0,a.jsx)(t.li,{children:"Integrity controls in the database that ensure data is not altered or destroyed unless by an authorized user with the appropriate permissions"}),"\n",(0,a.jsx)(t.li,{children:"Encrypted network transmissions"}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"breach-policy",children:"Breach Policy"}),"\n",(0,a.jsx)(t.p,{children:"In the event of a suspected data breach, a site lead may immediately revoke all credentials and immediately disable access to the data. As both a public and private key are required to decrypt exported data, and separate private keys are maintained per site and per patient, a data breach of one sub-section of the data cannot and will not affect other sub-sections or the entire platform. Furthermore, devices are identified by a unique per-device token and data integrity in flight can be ensured when reviewing the audit trail by cross-referencing this device-specific token. As noted above, LAMP does not record name but identifies users by codes so even with a breach, it will be hard to connect a person to their data."}),"\n",(0,a.jsx)(t.h3,{id:"risk-analysis-and-management",children:"Risk Analysis and Management"}),"\n",(0,a.jsx)(t.p,{children:"Our team performs frequent risk analysis as part of our security management processes. We take the following steps to mitigate risk:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Daily review of logs for all BIDMC-hosted research and clinical sites to pinpoint potential risks."}),"\n",(0,a.jsx)(t.li,{children:"Determine the probability of a major security issue occuring."}),"\n",(0,a.jsx)(t.li,{children:"Frequent security updates to proactively prevent new threats to LAMP's security."}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"security-threat-protocol",children:"Security Threat Protocol"}),"\n",(0,a.jsx)(t.p,{children:"In the unlikely event of an active security threat, our team will take the following steps:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Determine how and what information has been endangered."}),"\n",(0,a.jsx)(t.li,{children:"Alert users with steps (if any) they must take, such as changing their passwords."}),"\n",(0,a.jsx)(t.li,{children:"Identify and complete the necessary steps our team must take to secure our server, dashboard, and data."}),"\n",(0,a.jsx)(t.li,{children:"Log the type of threat, when and how it occured, and the resolution."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>s});var i=n(96540);const a={},r=i.createContext(a);function o(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0867371b.22fb2ab8.js b/assets/js/0867371b.c9bc9270.js similarity index 96% rename from assets/js/0867371b.22fb2ab8.js rename to assets/js/0867371b.c9bc9270.js index 271c6484ae..17b4daea8a 100644 --- a/assets/js/0867371b.22fb2ab8.js +++ b/assets/js/0867371b.c9bc9270.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2581],{78470:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>p,frontMatter:()=>r,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"using/learn","title":"L - Learn","description":"Tips and resources for patients and study participants are entered by researchers or clinicians through the Dashboard. Notifications for patients and study participants to review tips or resources can be preset and customized to be delivered at any time during the day.","source":"@site/docs/05-using/01-learn.md","sourceDirName":"05-using","slug":"/using/learn","permalink":"/using/learn","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/05-using/01-learn.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":1,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Publications with LAMP","permalink":"/about/publications"},"next":{"title":"A - Assess","permalink":"/using/assess"}}');var i=s(74848),n=s(28453);const r={},o="L - Learn",d={},c=[];function l(e){const t={h1:"h1",header:"header",img:"img",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"l---learn",children:"L - Learn"})}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{src:s(58907).A+"",width:"1064",height:"1026"})}),"\n",(0,i.jsx)(t.p,{children:"Tips and resources for patients and study participants are entered by researchers or clinicians through the Dashboard. Notifications for patients and study participants to review tips or resources can be preset and customized to be delivered at any time during the day."}),"\n",(0,i.jsx)(t.p,{children:"Clinicians and researchers offer patients and study participants useful health related tips and resources in the Learn tab. These tips can be used for patients and participants to teach themselves about specific topics, refresh their knowledge, or generally explore health-based resources."}),"\n",(0,i.jsx)(t.p,{children:"Some examples of what learn tips include are supported snippets of information accompanied by links that explain how to better your physical wellness, your sleep health, understanding that language around mental health providers, and more. It is also possible to enter have videos embedded within the app as well. If requested by a user, a clinician or researcher can also create individualized tips for a patient or participant to learn about. For example, if a patient was specifically struggling with social relationships (i.e. friendships, family dynamics, etc.), a set of tips in the Learn tab could be specifically created from the Dashboard for how to navigate and create healthy social relationships. See example of a resource tip and video tip below:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Resource Tip"}),(0,i.jsx)(t.th,{children:"Video Tip"})]})}),(0,i.jsx)(t.tbody,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:(0,i.jsx)(t.img,{src:s(89752).A+"",width:"828",height:"1792"})}),(0,i.jsx)(t.td,{children:(0,i.jsx)(t.img,{src:s(10881).A+"",width:"828",height:"1792"})})]})})]})]})}function p(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},58907:(e,t,s)=>{s.d(t,{A:()=>a});const a=s.p+"assets/images/learn-ceb3601c1e4f3d661f252c49dc6caedd.png"},10881:(e,t,s)=>{s.d(t,{A:()=>a});const a=s.p+"assets/images/learn2-b25e6dcbb9bcf5382f62e57aa180af7e.png"},89752:(e,t,s)=>{s.d(t,{A:()=>a});const a=s.p+"assets/images/learn3-008632bc3d72e814f1bb50ecc5974a23.png"},28453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>o});var a=s(96540);const i={},n=a.createContext(i);function r(e){const t=a.useContext(n);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),a.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2581],{78470:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>p,frontMatter:()=>r,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"using/learn","title":"L - Learn","description":"Tips and resources for patients and study participants are entered by researchers or clinicians through the Dashboard. Notifications for patients and study participants to review tips or resources can be preset and customized to be delivered at any time during the day.","source":"@site/docs/05-using/01-learn.md","sourceDirName":"05-using","slug":"/using/learn","permalink":"/using/learn","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/05-using/01-learn.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":1,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Publications with LAMP","permalink":"/about/publications"},"next":{"title":"A - Assess","permalink":"/using/assess"}}');var i=s(74848),n=s(28453);const r={},o="L - Learn",d={},c=[];function l(e){const t={h1:"h1",header:"header",img:"img",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"l---learn",children:"L - Learn"})}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{src:s(58907).A+"",width:"1064",height:"1026"})}),"\n",(0,i.jsx)(t.p,{children:"Tips and resources for patients and study participants are entered by researchers or clinicians through the Dashboard. Notifications for patients and study participants to review tips or resources can be preset and customized to be delivered at any time during the day."}),"\n",(0,i.jsx)(t.p,{children:"Clinicians and researchers offer patients and study participants useful health related tips and resources in the Learn tab. These tips can be used for patients and participants to teach themselves about specific topics, refresh their knowledge, or generally explore health-based resources."}),"\n",(0,i.jsx)(t.p,{children:"Some examples of what learn tips include are supported snippets of information accompanied by links that explain how to better your physical wellness, your sleep health, understanding that language around mental health providers, and more. It is also possible to enter have videos embedded within the app as well. If requested by a user, a clinician or researcher can also create individualized tips for a patient or participant to learn about. For example, if a patient was specifically struggling with social relationships (i.e. friendships, family dynamics, etc.), a set of tips in the Learn tab could be specifically created from the Dashboard for how to navigate and create healthy social relationships. See example of a resource tip and video tip below:"}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{children:"Resource Tip"}),(0,i.jsx)(t.th,{children:"Video Tip"})]})}),(0,i.jsx)(t.tbody,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{children:(0,i.jsx)(t.img,{src:s(89752).A+"",width:"828",height:"1792"})}),(0,i.jsx)(t.td,{children:(0,i.jsx)(t.img,{src:s(10881).A+"",width:"828",height:"1792"})})]})})]})]})}function p(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},58907:(e,t,s)=>{s.d(t,{A:()=>a});const a=s.p+"assets/images/learn-ceb3601c1e4f3d661f252c49dc6caedd.png"},10881:(e,t,s)=>{s.d(t,{A:()=>a});const a=s.p+"assets/images/learn2-b25e6dcbb9bcf5382f62e57aa180af7e.png"},89752:(e,t,s)=>{s.d(t,{A:()=>a});const a=s.p+"assets/images/learn3-008632bc3d72e814f1bb50ecc5974a23.png"},28453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>o});var a=s(96540);const i={},n=a.createContext(i);function r(e){const t=a.useContext(n);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),a.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0b7351dc.c173c10f.js b/assets/js/0b7351dc.8cdef510.js similarity index 99% rename from assets/js/0b7351dc.c173c10f.js rename to assets/js/0b7351dc.8cdef510.js index f0eb396b32..35544a8f66 100644 --- a/assets/js/0b7351dc.c173c10f.js +++ b/assets/js/0b7351dc.8cdef510.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[18],{82177:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"start_here/activities/customize_activities","title":"Customize and Schedule Activities","description":"To create any activity that shows up on the manage page (e.g. Jewels A or B):","source":"@site/docs/06-start_here/06-activities/06-customize_activities.md","sourceDirName":"06-start_here/06-activities","slug":"/start_here/activities/customize_activities","permalink":"/start_here/activities/customize_activities","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/06-activities/06-customize_activities.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":6,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create and Customize Activities","permalink":"/start_here/activities/create_activities"},"next":{"title":"Take Surveys and Complete Activities","permalink":"/start_here/activities/complete_activities"}}');var a=i(74848),n=i(28453);const o={},c="Customize and Schedule Activities",r={},l=[{value:"Some examples of activities you can customize:",id:"some-examples-of-activities-you-can-customize",level:3},{value:"Jewels A and Jewels B",id:"jewels-a-and-jewels-b",level:3},{value:"Breathe (Mindfulness)",id:"breathe-mindfulness",level:3},{value:"Journal",id:"journal",level:3}];function d(e){const t={code:"code",em:"em",h1:"h1",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"customize-and-schedule-activities",children:"Customize and Schedule Activities"})}),"\n",(0,a.jsx)(t.p,{children:"To create any activity that shows up on the manage page (e.g. Jewels A or B):"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsxs)(t.li,{children:["Click the ",(0,a.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to begin."]}),"\n",(0,a.jsx)(t.li,{children:"Choose the activity you would like to add."}),"\n",(0,a.jsx)(t.li,{children:"Select the study you wish to add it to."}),"\n",(0,a.jsx)(t.li,{children:"Add a title."}),"\n",(0,a.jsx)(t.li,{children:"Add a description if it is appropriate."}),"\n",(0,a.jsx)(t.li,{children:"Add an icon by clicking on the camera icon and uploading your desired image."}),"\n",(0,a.jsx)(t.li,{children:"Click Save to save your activity."}),"\n",(0,a.jsx)(t.li,{children:"See some examples of different activities below."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(84175).A+"",width:"680",height:"1058"})}),"\n",(0,a.jsx)(t.h3,{id:"some-examples-of-activities-you-can-customize",children:"Some examples of activities you can customize:"}),"\n",(0,a.jsx)(t.p,{children:"Note: You are able to change the icon by clicking the trash can to delete the current one. From there follow the same steps as above for adding your own icon. Please note that any image you wish to upload must be less than 1mb in size and either a png, svg, or jpeg file type."}),"\n",(0,a.jsx)(t.h3,{id:"jewels-a-and-jewels-b",children:"Jewels A and Jewels B"}),"\n",(0,a.jsx)(t.p,{children:"For both Jewels A and Jewels B, you are able to input specifics such as game duration. You can also edit the number of diamonds, points, and shapes of the diamonds."}),"\n",(0,a.jsx)(t.p,{children:"To edit any of these, simply click on the box and enter your desired number."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(84494).A+"",width:"1744",height:"1120"})}),"\n",(0,a.jsx)(t.h3,{id:"breathe-mindfulness",children:"Breathe (Mindfulness)"}),"\n",(0,a.jsx)(t.p,{children:'You are able to either copy a URL and paste it into a breathe activity, or you can upload a previously recorded audio file by selecting "Upload Audio" and importing it.'}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(52007).A+"",width:"1744",height:"772"})}),"\n",(0,a.jsx)(t.h3,{id:"journal",children:"Journal"}),"\n",(0,a.jsx)(t.p,{children:"Once you create your journal activity, it will show up in the Manage tab. However, you are only able to view the results in the Prevent tab."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(33).A+"",width:"1704",height:"296"})}),"\n",(0,a.jsx)(t.h1,{id:"scheduling-an-activity",children:"Scheduling an Activity"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Log into the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsx)(t.li,{children:"Select the activity you would like to schedule by checking the box next to it's name."}),"\n",(0,a.jsx)(t.li,{children:"Click the arrow to the right of the Name."}),"\n",(0,a.jsx)(t.li,{children:"Click the plus sign to the far right to add a schedule."}),"\n",(0,a.jsx)(t.li,{children:"Select you Start Date, Time, Repeat Interval, etc."}),"\n",(0,a.jsx)(t.li,{children:"Click the check mark."}),"\n",(0,a.jsx)(t.li,{children:"The patient or participant will receive a feed item and a notification on their phone at the specified time."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(67833).A+"",width:"1744",height:"920"})}),"\n",(0,a.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/LegFC4ZB1ro",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:"How to schedule an activity from the Patient Profile"})})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},84175:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},52007:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/breathe-0302c42f3ef9d3997bb543fb7d9a97e6.jpg"},84494:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/jewels-747030fe8d387b0f356d15c1268589e7.jpg"},33:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/journal-fceb3d4495c87d47ff7f411ac7385e91.jpg"},67833:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/schedule-3b79ac50f4c51a0017bb81f1c062148b.jpg"},28453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>c});var s=i(96540);const a={},n=s.createContext(a);function o(e){const t=s.useContext(n);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),s.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[18],{82177:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"start_here/activities/customize_activities","title":"Customize and Schedule Activities","description":"To create any activity that shows up on the manage page (e.g. Jewels A or B):","source":"@site/docs/06-start_here/06-activities/06-customize_activities.md","sourceDirName":"06-start_here/06-activities","slug":"/start_here/activities/customize_activities","permalink":"/start_here/activities/customize_activities","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/06-activities/06-customize_activities.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":6,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create and Customize Activities","permalink":"/start_here/activities/create_activities"},"next":{"title":"Take Surveys and Complete Activities","permalink":"/start_here/activities/complete_activities"}}');var a=i(74848),n=i(28453);const o={},c="Customize and Schedule Activities",r={},l=[{value:"Some examples of activities you can customize:",id:"some-examples-of-activities-you-can-customize",level:3},{value:"Jewels A and Jewels B",id:"jewels-a-and-jewels-b",level:3},{value:"Breathe (Mindfulness)",id:"breathe-mindfulness",level:3},{value:"Journal",id:"journal",level:3}];function d(e){const t={code:"code",em:"em",h1:"h1",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"customize-and-schedule-activities",children:"Customize and Schedule Activities"})}),"\n",(0,a.jsx)(t.p,{children:"To create any activity that shows up on the manage page (e.g. Jewels A or B):"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsxs)(t.li,{children:["Click the ",(0,a.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to begin."]}),"\n",(0,a.jsx)(t.li,{children:"Choose the activity you would like to add."}),"\n",(0,a.jsx)(t.li,{children:"Select the study you wish to add it to."}),"\n",(0,a.jsx)(t.li,{children:"Add a title."}),"\n",(0,a.jsx)(t.li,{children:"Add a description if it is appropriate."}),"\n",(0,a.jsx)(t.li,{children:"Add an icon by clicking on the camera icon and uploading your desired image."}),"\n",(0,a.jsx)(t.li,{children:"Click Save to save your activity."}),"\n",(0,a.jsx)(t.li,{children:"See some examples of different activities below."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(84175).A+"",width:"680",height:"1058"})}),"\n",(0,a.jsx)(t.h3,{id:"some-examples-of-activities-you-can-customize",children:"Some examples of activities you can customize:"}),"\n",(0,a.jsx)(t.p,{children:"Note: You are able to change the icon by clicking the trash can to delete the current one. From there follow the same steps as above for adding your own icon. Please note that any image you wish to upload must be less than 1mb in size and either a png, svg, or jpeg file type."}),"\n",(0,a.jsx)(t.h3,{id:"jewels-a-and-jewels-b",children:"Jewels A and Jewels B"}),"\n",(0,a.jsx)(t.p,{children:"For both Jewels A and Jewels B, you are able to input specifics such as game duration. You can also edit the number of diamonds, points, and shapes of the diamonds."}),"\n",(0,a.jsx)(t.p,{children:"To edit any of these, simply click on the box and enter your desired number."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(84494).A+"",width:"1744",height:"1120"})}),"\n",(0,a.jsx)(t.h3,{id:"breathe-mindfulness",children:"Breathe (Mindfulness)"}),"\n",(0,a.jsx)(t.p,{children:'You are able to either copy a URL and paste it into a breathe activity, or you can upload a previously recorded audio file by selecting "Upload Audio" and importing it.'}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(52007).A+"",width:"1744",height:"772"})}),"\n",(0,a.jsx)(t.h3,{id:"journal",children:"Journal"}),"\n",(0,a.jsx)(t.p,{children:"Once you create your journal activity, it will show up in the Manage tab. However, you are only able to view the results in the Prevent tab."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(33).A+"",width:"1704",height:"296"})}),"\n",(0,a.jsx)(t.h1,{id:"scheduling-an-activity",children:"Scheduling an Activity"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Log into the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsx)(t.li,{children:"Select the activity you would like to schedule by checking the box next to it's name."}),"\n",(0,a.jsx)(t.li,{children:"Click the arrow to the right of the Name."}),"\n",(0,a.jsx)(t.li,{children:"Click the plus sign to the far right to add a schedule."}),"\n",(0,a.jsx)(t.li,{children:"Select you Start Date, Time, Repeat Interval, etc."}),"\n",(0,a.jsx)(t.li,{children:"Click the check mark."}),"\n",(0,a.jsx)(t.li,{children:"The patient or participant will receive a feed item and a notification on their phone at the specified time."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(67833).A+"",width:"1744",height:"920"})}),"\n",(0,a.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/LegFC4ZB1ro",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:"How to schedule an activity from the Patient Profile"})})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},84175:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},52007:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/breathe-0302c42f3ef9d3997bb543fb7d9a97e6.jpg"},84494:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/jewels-747030fe8d387b0f356d15c1268589e7.jpg"},33:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/journal-fceb3d4495c87d47ff7f411ac7385e91.jpg"},67833:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/schedule-3b79ac50f4c51a0017bb81f1c062148b.jpg"},28453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>c});var s=i(96540);const a={},n=s.createContext(a);function o(e){const t=s.useContext(n);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),s.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0cbd09b8.a66affb0.js b/assets/js/0cbd09b8.8e670207.js similarity index 99% rename from assets/js/0cbd09b8.a66affb0.js rename to assets/js/0cbd09b8.8e670207.js index 648fec6a74..4e3607c115 100644 --- a/assets/js/0cbd09b8.a66affb0.js +++ b/assets/js/0cbd09b8.8e670207.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[221],{80239:(A,e,t)=>{t.r(e),t.d(e,{assets:()=>f,contentTitle:()=>a,default:()=>Q,frontMatter:()=>v,metadata:()=>r,toc:()=>g});const r=JSON.parse('{"id":"data_science/r","title":"Preparing to Analyze Your Data in R","description":"If you\'d like to follow along with this tutorial but don\'t have an R development environment set up, consider using RStudio Cloud, a free service from the RStudio team.","source":"@site/docs/09-data_science/05-r.md","sourceDirName":"09-data_science","slug":"/data_science/r","permalink":"/data_science/r","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/05-r.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":5,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Preparing to Analyze Your Data in Python","permalink":"/data_science/python"},"next":{"title":"Cortex Quick Start Guide","permalink":"/data_science/cortex/getting-started"}}');var n=t(74848),d=t(28453);const v={},a="Preparing to Analyze Your Data in R",f={},g=[{value:"Connect to your LAMP server.",id:"connect-to-your-lamp-server",level:2},{value:"Download data from the LAMP server.",id:"download-data-from-the-lamp-server",level:2},{value:"Code Output",id:"code-output",level:3},{value:"Optional: Output the data to a CSV.",id:"optional-output-the-data-to-a-csv",level:2},{value:"Check out all the activities in the study",id:"check-out-all-the-activities-in-the-study",level:2},{value:"Code Output",id:"code-output-1",level:3},{value:"Get number of participants in the study",id:"get-number-of-participants-in-the-study",level:2},{value:"Code Output",id:"code-output-2",level:3},{value:"Get engagement and plot activity histogram",id:"get-engagement-and-plot-activity-histogram",level:2},{value:"Code Output",id:"code-output-3",level:3},{value:"Code Output",id:"code-output-4",level:3},{value:"Get mean and standard deviation for any survey scale",id:"get-mean-and-standard-deviation-for-any-survey-scale",level:2},{value:"Code Output",id:"code-output-5",level:3},{value:"Code Output",id:"code-output-6",level:3},{value:"Plot survey scores over time for an individual participant",id:"plot-survey-scores-over-time-for-an-individual-participant",level:2},{value:"Compare self-reported anxiety with self-reported problematic internet use",id:"compare-self-reported-anxiety-with-self-reported-problematic-internet-use",level:2}];function o(A){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",p:"p",pre:"pre",strong:"strong",...(0,d.R)(),...A.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.header,{children:(0,n.jsx)(e.h1,{id:"preparing-to-analyze-your-data-in-r",children:"Preparing to Analyze Your Data in R"})}),"\n",(0,n.jsxs)(e.p,{children:["If you'd like to follow along with this tutorial but don't have an R development environment set up, ",(0,n.jsxs)(e.strong,{children:["consider using ",(0,n.jsx)(e.a,{href:"https://rstudio.cloud/",children:"RStudio Cloud"}),", a free service"]})," from the RStudio team."]}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.strong,{children:"The majority of the code and directions in this page are now deprecated and integrated in the LAMP API. See 'Preparing to Analyze Your Data in Python' for up-to-date data analysis steps."})}),"\n",(0,n.jsx)(e.h2,{id:"connect-to-your-lamp-server",children:"Connect to your LAMP server."}),"\n",(0,n.jsx)(e.p,{children:"First, install the LAMP client library."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"install.packages(\"devtools\")\ndevtools::install_github('BIDMCDigitalPsychiatry/LAMP-r') \n"})}),"\n",(0,n.jsxs)(e.p,{children:["Then connect to the LAMP API. Your Researcher ID comes from the dashboard at ",(0,n.jsx)(e.code,{children:"dashboard.lamp.digital"}),"."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"library(LAMP)\nLAMP <- LAMP$new('https://api.lamp.digital', 'your_email_here@email.com', 'your_password_here')\nresearcher_id <- \"YOUR_RESEARCHER_ID\"\n"})}),"\n",(0,n.jsx)(e.h2,{id:"download-data-from-the-lamp-server",children:(0,n.jsx)(e.strong,{children:"Download data from the LAMP server."})}),"\n",(0,n.jsx)(e.p,{children:"First, download all Participants and retrieve the ID mapping for all Activities in our Study."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"library(dplyr)\nlibrary(anytime)\nlibrary(data.table)\n\nparticipants <- LAMP$Participant$allByStudy(researcher_id) %>% pull(id)\nactivity_map <- LAMP$Activity$allByStudy(researcher_id) %>% \n dplyr::select(id,name) %>%\n\t\trename(activity = id)\n"})}),"\n",(0,n.jsxs)(e.p,{children:["Now we run some pre-processing to flatten the nested data structure that we receive from the ",(0,n.jsx)(e.code,{children:"ActivityEvent"})," API for each Participant, performed in a loop over all Participants in our Study. Because some entries may be ",(0,n.jsx)(e.code,{children:"null"})," (missing or invalid), we ignore those and flatten the data after converting time stamps from the ",(0,n.jsx)(e.code,{children:"UNIX Epoch"})," standard to the human-readable ",(0,n.jsx)(e.code,{children:"YYYY-MM-DD"})," format. There\u2019s a workaround for excessively-nested survey items as well."]}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.strong,{children:"The below section of code is now deprecated and integrated into the LAMP API."})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'data_list <- list()\nfor (i in 1:length(participants)) {\n tmp <- LAMP$ActivityEvent$allByParticipant(participants[i])\n if (length(tmp) > 0) {\n tmp <- right_join(activity_map %>% select(activity, name), \n jsonlite::flatten(tmp) %>% \n mutate(timestamp = anytime(as.numeric(timestamp)/1000, tz = "America/New_York")) %>%\n rename(activity_duration = duration) %>% \n mutate(id = participants[i]),\n by="activity")\n tmp_event_list <- list()\n for (j in 1:nrow(tmp)) {\n if (length(tmp[j,]$temporal_events[[1]]) > 0) {\n\t\t\t\ttmp_event_list[[j]] <- cbind(tmp[j,], tmp[j,]$temporal_events[[1]], row.names=F) %>% \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdplyr::select(-temporal_events)\n }\n }\n data_list[[i]] <- rbindlist(tmp_event_list, fill = T)\n }\n}\ndata_list[sapply(data_list, is.null)] <- NULL\n'})}),"\n",(0,n.jsxs)(e.p,{children:["Now, we combine the data frames we\u2019ve pre-processed and ensure they follow the proper data format. Once we reorder the columns to include only variables of interest, we can call the ",(0,n.jsx)(e.code,{children:"head()"})," function to preview the data frame. To view all available variables in your data frame, use ",(0,n.jsx)(e.code,{children:"colnames(result_events_mod)"}),".\nSome of the columns we\u2019re selecting tell us about meta information about the Activity (such as whether it\u2019s a survey or game), the individual survey question or game level results, and other optional game data (",(0,n.jsx)(e.code,{children:"static_data"}),", which may include ",(0,n.jsx)(e.code,{children:"NA"})," values). To learn more about what each of these columns contains, represents, and can be used for, please see the ",(0,n.jsx)(e.a,{href:"https://www.notion.so/e1a2115ca5d44f96b458fc90c8d49932"})," help topic."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"result_events <- rbindlist(data_list, fill = T) %>% \n\tmutate(id = as.character(id)) %>% \n\tmutate(activity = as.character(activity)) %>% \n\tmutate(name = as.character(name)) \n\nhead(results)\n"})}),"\n",(0,n.jsx)(e.h3,{id:"code-output",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"id timestamp name item value\n1 U1094374134 2019-12-08 PHQ-8 How often did you feel bad about yourself, or that you were a failure or let your family down? 1\n2 U1094374134 2019-12-08 PHQ-8 How often did have you have trouble concentrating on things such as reading or watching tv? 1\n3 U1094374134 2019-12-08 PHQ-8 How often did you find yourself moving so slowly, or so fidgety/restless, that others noticed? 1\n4 U1094374134 2019-12-08 PHQ-8 How often did you have trouble falling or staying asleep, or sleep for more hours than you meant to? 1\n5 U1094374134 2019-12-08 PHQ-8 How often did you feel tired or like you had little energy? 1\n6 U1094374134 2019-12-08 PHQ-8 How often did you find yourself with no appetite, or eating more than you meant to? 1\n"})}),"\n",(0,n.jsxs)(e.h2,{id:"optional-output-the-data-to-a-csv",children:["Optional: ",(0,n.jsx)(e.strong,{children:"Output the data to a CSV."})]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'write.csv(results, "./output-1-27-20.csv", row.names = F)\n'})}),"\n",(0,n.jsx)(e.h1,{id:"appendix-sample-analyses",children:(0,n.jsx)(e.strong,{children:"Appendix: Sample Analyses"})}),"\n",(0,n.jsx)(e.h2,{id:"check-out-all-the-activities-in-the-study",children:"Check out all the activities in the study"}),"\n",(0,n.jsx)(e.p,{children:"This includes both default activities and custom activities."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"activity_map %>% select(activity, spec, name)\n"})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-1",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"## activity spec name\n## 1 QWN0aXZpdHk6MDoxMDM6MjM~ lamp.group Daily Survey Check-In\n## 2 QWN0aXZpdHk6MToxMDM6MzIw lamp.survey PHQ-8\n## 3 QWN0aXZpdHk6MToxMDM6MzQx lamp.survey Instructions\n## 4 QWN0aXZpdHk6MToxMDM6MzQy lamp.survey GAD-7\n## 5 QWN0aXZpdHk6MToxMDM6MzQz lamp.survey PIU-SF-6\n## 6 QWN0aXZpdHk6MToxMDM6MzQ0 lamp.survey Warning\n## 7 QWN0aXZpdHk6MToxMDM6MzQ1 lamp.survey Qualitative Digital Media Use Assessment\n## 8 QWN0aXZpdHk6MToxMDM6MzQ2 lamp.survey Screen Time Use - iPhones only\n## 9 QWN0aXZpdHk6MToxMDM6MzQ3 lamp.survey iPhone/Android Assessment\n## 10 QWN0aXZpdHk6MjoxMDM6MA~~ lamp.nback N-Back\n## 11 QWN0aXZpdHk6MzoxMDM6MA~~ lamp.trails_b Trails B\n## 12 QWN0aXZpdHk6NDoxMDM6MA~~ lamp.spatial_span Spatial Span\n## 13 QWN0aXZpdHk6NToxMDM6MA~~ lamp.simple_memory Simple Memory\n## 14 QWN0aXZpdHk6NjoxMDM6MA~~ lamp.serial7s Serial 7s\n## 15 QWN0aXZpdHk6NzoxMDM6MA~~ lamp.cats_and_dogs Cats and Dogs\n## 16 QWN0aXZpdHk6ODoxMDM6MA~~ lamp.3d_figure_copy 3D Figure Copy\n## 17 QWN0aXZpdHk6OToxMDM6MA~~ lamp.visual_association Visual Association\n## 18 QWN0aXZpdHk6MTA6MTAzOjA~ lamp.digit_span Digit Span\n## 19 QWN0aXZpdHk6MTE6MTAzOjA~ lamp.cats_and_dogs_new Cats and Dogs New\n## 20 QWN0aXZpdHk6MTI6MTAzOjA~ lamp.temporal_order Temporal Order\n## 21 QWN0aXZpdHk6MTM6MTAzOjA~ lamp.nback_new N-Back New\n## 22 QWN0aXZpdHk6MTQ6MTAzOjA~ lamp.trails_b_new Trails B New\n## 23 QWN0aXZpdHk6MTU6MTAzOjA~ lamp.trails_b_dot_touch Trails B Dot Touch\n## 24 QWN0aXZpdHk6MTY6MTAzOjA~ lamp.jewels_a Jewels Trails A\n## 25 QWN0aXZpdHk6MTc6MTAzOjA~ lamp.jewels_b Jewels Trails B\n## 26 QWN0aXZpdHk6MTg6MTAzOjA~ lamp.scratch_image Scratch Image\n## 27 QWN0aXZpdHk6MTk6MTAzOjA~ lamp.spin_wheel Spin Wheel\n"})}),"\n",(0,n.jsx)(e.h2,{id:"get-number-of-participants-in-the-study",children:"Get number of participants in the study"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'print(paste("Number of Participants:", length(participants)))\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-2",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:'## [1] "Number of Participants: 29"\n'})}),"\n",(0,n.jsx)(e.h2,{id:"get-engagement-and-plot-activity-histogram",children:"Get engagement and plot activity histogram"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'engagement_data <- inner_join(results %>% dplyr::count(id), \n results %>% group_by(id) %>% filter(row_number()==n()) %>% select(id, timestamp), \n by="id") %>% \n rename(activities.completed = n) %>% rename(most.recent.activity = timestamp)\n\nengagement_data\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-3",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"## # A tibble: 27 x 3\n## id activities.completed most.recent.activity\n## \n## 1 U1005979819 659 2019-11-16 22:50:57 \n## 2 U1094374134 2085 2019-08-14 12:23:15 \n## 3 U1126469507 503 2019-12-10 21:52:20 \n## 4 U1232915366 226 2020-01-29 00:51:34 \n## 5 U1235780769 767 2019-12-09 20:08:02 \n## 6 U1367615199 813 2019-11-13 16:11:09 \n## 7 U1500960001 742 2019-10-25 21:26:24 \n## 8 U1680931766 1070 2019-12-13 22:41:58 \n## 9 U176381486 585 2019-11-08 18:45:24 \n## 10 U2127860149 170 2019-11-13 16:51:52 \n## # \u2026 with 17 more rows\n"})}),"\n",(0,n.jsx)(e.p,{children:"Let's view a histogram representation of the data."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"hist(engagement_data$activities.completed, breaks=15)\n"})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-4",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.p,{children:"![../Topics/Preparing to analyze your data in R/Untitled.png](../Topics/Preparing to analyze your data in R/Untitled.png)"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{src:"data:image/png;base64,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",alt:""})}),"\n",(0,n.jsx)(e.h2,{id:"get-mean-and-standard-deviation-for-any-survey-scale",children:"Get mean and standard deviation for any survey scale"}),"\n",(0,n.jsxs)(e.p,{children:["We\u2019ll include only anxiety survey (",(0,n.jsx)(e.code,{children:"GAD-7"}),") results and parse/convert their answer data to numbers using the ",(0,n.jsx)(e.code,{children:"readr"})," library. Then, we aggregate by timestamp (which is unique to each Activity), and summarize the table."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'library(readr)\n\ndata <- results %>% \n filter(name == "GAD-7") %>% \n mutate(value = as.numeric(parse_number(as.character(value)))) %>%\n group_by(id,timestamp) %>%\n summarise(average_GAD = mean(value))\n\nsummary(data$average_GAD)\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-5",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"## Min. 1st Qu. Median Mean 3rd Qu. Max. \n## 0.0000 0.4286 0.8571 0.9139 1.4286 3.0000\n"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'print(paste("Mean GAD-7 across all participants:", round(mean(data$average_GAD), 3), "\xb1", round(sd(data$average_GAD), 3)))\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-6",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:'## [1] "Mean GAD-7 across all participants: 0.914 \xb1 0.667"\n'})}),"\n",(0,n.jsx)(e.h2,{id:"plot-survey-scores-over-time-for-an-individual-participant",children:"Plot survey scores over time for an individual participant"}),"\n",(0,n.jsxs)(e.p,{children:["Filter the first Participant\u2019s mood (",(0,n.jsx)(e.code,{children:"PHQ-8"}),") results and parse the strings into numbers as they may be either numeric or text. Then, we aggregate by timestamp, which is unique for each Activity, and take the mean of all scores for a given timestamp."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'data <- results %>% \n filter(id == participants[1] & name == "PHQ-8") %>%\n mutate(value = as.numeric(as.character(value))) %>%\n group_by(timestamp) %>%\n summarise(average_score = mean(value))\n'})}),"\n",(0,n.jsxs)(e.p,{children:["Plot the now-filtered data using the ",(0,n.jsx)(e.code,{children:"ggplot2"})," library; you\u2019ll find our sample graph below."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'library(ggplot2)\nggplot(data, aes(x = timestamp, y = average_score)) +\n geom_line(size=1, color="steelblue") +\n theme_minimal(base_size = 15) +\n ylim(0,4) +\n theme(\n panel.grid.major = element_blank(),\n panel.background = element_blank(),\n axis.line = element_line(colour = "black"),\n axis.title.x = element_text(size = 15))\n'})}),"\n",(0,n.jsx)(e.h2,{id:"compare-self-reported-anxiety-with-self-reported-problematic-internet-use",children:"Compare self-reported anxiety with self-reported problematic internet use"}),"\n",(0,n.jsxs)(e.p,{children:["First, we filter data, using a left-join (which is like a merge operation) between the ",(0,n.jsx)(e.code,{children:"GAD-7"})," and ",(0,n.jsx)(e.code,{children:"PIU-6"})," survey instruments, such that each participant is a single row. All answer data is converted to numeric values first, and then we aggregate by ID, which is unique to each Activity. Finally, we take the mean of all scores for a given timestamp."]}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{src:"data:image/png;base64,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AIgBAR4AAABiQIAHAACAGBDgAQAAIAYEeAAAAIgBAR4AAABiQIAHAACAGBDgAQAAIAYEeAAAAIgBAR4AAABiQIAHAACAGBDgAQAAIAbyD8zHVFdX/+1vf9u6dWt1dXV1dfWYMWMuvPDC6KVEIpGTk3NgygAAAICYymyAr66uvuGGG5YsWbJy5cq2trb250855ZQowNfW1k6dOvWMM8743Oc+N23atIwWAwAAAPGVwSX0ixYtmjp16rXXXvvyyy93TO9JSktLb7vttunTp1911VXNzc2ZqwcAAADiK1MBfsGCBZdccsn27dv38PpEInHdddddcMEFra2tGSoJAAAA4isjAf6uu+664oor2h9OnTp1wYIFf/rTn954442kKwsLCy+//PLi4uLo4T333HP99ddnoiQAAACItfQH+Obm5i9/+cvROD8///vf//7KlSsvv/zyOXPmjBs3LunivLy8BQsWrF27dubMmdEz1157bVlZWdqrAgAAgFhLf4C/++67N23aFI2vu+66K6+8sqCgoOdbxo4d++ijj44ePTqEUF9f/7Of/SztVQEAAECspT/A33vvvdEg6i2/h3eNHDly/vz50fiRRx5Je1UAAAAQa+kP8GvWrIkGn/jEJ/bqxjlz5kSD5cuXp7kmAAAAiLn0B/h169ZFg6OOOmqvbpw0aVI0sAceAAAAkqQ/wA8YMCAaNDU17dWNpaWl0WDgwIFprgkAAABiLv0Bvr3V/HPPPbdXN7avnB87dmyaawIAAICYS3+AP+GEE6LBDTfc0NDQsOc3PvDAA9Fg1qxZaa8KAAAAYi39Af7cc8+NBsuXL//Upz61h3fde++9v/vd76LxmWeemfaqAAAAINbSH+BPPfXU97znPdH49ttvP/3001evXt3D9YlEYtGiRfPmzYseTpky5Zxzzkl7VQAAABBr+Zl401tvvfWd73znrl27QghLly59+OGHzzzzzOOOO+7YY4+NLmhqalq7du3mzZuffvrpO++885VXXomez83NvemmmwoKCjJRFQAAAMRXRgL8kUce+fDDD5922mnRgXDNzc1LlixZsmRJ+wVPPvnk1KlTk+7Kycm55ZZb3ve+92WiJAAAAIi19C+hj8yaNWvFihVz587dw+sPPvjgRx555NJLL81QPQAAABBrmQrwIYSSkpLFixe//PLLn/70p6dMmdLlNYWFhbNnz77jjjtWr1590kknZa4YAAAAiLWMLKHv6Jhjjlm4cOHChQvLyspWrFhRXl5eUVGRl5c3YsSIcePGzZgxw453AAAA2K2MB/h2o0aNmj179gH7OAAAAOhL0r+E/uabb54+ffr06dPf9ra3pf3NAQAAoH9K/wz82rVrV6xYEY3r6+uLiorS/hEAAADQ36R/Bv7QQw9tH7cf8A4AAADsj/QH+Llz5w4aNCgaL126NO3vDwAAAP1Q+gP8hAkTvvOd70Tjm266qaysLO0fAQAAAP1NRs6B/8xnPvO9730vJydnx44dp59++ubNmzPxKQAAANB/ZOoYuauuumrWrFkXX3zxs88+e9RRR51//vnvfOc7J0yYMGHChGHDhuXk5PRw74QJEzJUFQAAAMRURgL89OnTo0Fubm4Ioaam5rbbbrvtttv28PZEIpGJqgAAACC+MhLg24+RAwAAANIiI3vgAQAAgPTKyAz8Cy+8kIm3BQAAgH4rIwF+1qxZmXhbAAAA6LcsoQcAAIAYyNQxcv1Bc3Pzzp07s11FP1JRUZHtEiBm6uvr6+vrs10FxFhtbW1tbW22q4AY8y8RpBo1alTPB6v34MAF+A0bNqxfv76ysrKysnLQoEEjRoyYOHHiEUccsc+lAwAAQP+R2QDf2tq6dOnS22+//amnniorK0u9YNiwYSeccMIll1xy5pln5ufHbDnAgAEDDjrooGxX0S9UVlY2NzcPHz48dl8kkC0NDQ01NTVFRUXFxcXZrgViqb6+vra2tri4uKioKNu1QCw1NjZWV1f7lwjSK4N74J966qlp06a9//3v/93vftdleg8hVFZWLl26dO7cuUcfffRf/vKXzBUDAAAAsZapAP/jH/949uzZq1at2sPrX3vttfe85z233357huoBAACAWMvIguT777//sssuSyQS0cOioqLTTz/9He94x6RJkyZOnDhu3LiysrKNGzdu3Ljx2Wefve+++6LOFm1tbR/72McmTJhw2mmnZaIqAAAAiK/0B/iGhoZPf/rTbW1t0cNPfOIT3/jGN5L2ik+ePLn9rPiysrKrr776xz/+cQihtbV1/vz5K1euLCgoSHthAAAAEF/pX0L/61//euPGjdF4wYIF//M//9Nzp7dRo0bdeuut3/ve96KHa9asueeee9JeFQAAAMRa+gP873//+2hwyimnXH755Xt411VXXXXyySdH4/vvvz/tVQEAAECspT/Av/TSS9Hg4x//+F7d+IlPfCLpHQAAAIBI+gP8tm3bosH06dP36sY3v/nN0aC0tDTNNQEAAEDMpT/ANzc3R4MBAwbs1Y3tjeva3wEAAACIpD/AjxkzJhqsXr16r25sv37s2LFprgkAAABiLv0B/sgjj4wGP//5z/fqxjvvvDPpHQAAAIBI+gP8mWeeGQ1+8YtfPPDAA3t41x//+Mf2wH/GGWekvSoAAACItfQH+Hnz5o0YMSKEkEgk5s6d+8Mf/rCtra2H69va2n7yk5+cddZZiUQihDBixIjzzz8/7VUBAABArKU/wI8aNeqb3/xmNG5qapo/f/60adO+853vPP744+vWrWtqaoqeX79+/RNPPPH9739/xowZH/vYxxobG6NbvvnNb44cOTLtVQEAAECs5WfiTT/5yU+uWbPmxhtvjB6++uqrV199dTTOyckZNmxYZWVlNN+e5LOf/ewnP/nJTJQEAAAAsZb+GfjIggULbrnlliFDhiQ9n0gkKioqUtP74MGDf/jDH7ZnfgAAAKCjTAX4EMLHP/7xVatWXXvttZMnT+7hskMOOeTrX//6qlWrPvnJT+bk5GSuHgAAAIivjCyhbzdu3Livfe1rX/va1zZt2vT888+//vrrFRUVNTU1gwcPHjZs2MEHH3zssccefPDBGa0BAAAA+oDMBvh2kyZNmjRp0oH5LAAAAOh7MriEfk/0fMIcAAAAEMlsgC8vL//Zz3720Y9+9Jxzzkl9tba2tri4eObMmV/60pdWrlyZ0UoAAAAg1jK1hL6xsfEb3/jGggUL6uvrQwgTJ07s8rKGhobly5cvX778uuuu+8hHPvLf//3fgwYNylBJAAAAEF8ZCfDV1dWnn376U089tee3tLW13XbbbcuWLXvssceKi4szURUAAADEV0aW0F922WUd03tJSclZZ52VellhYeH111//3ve+t6CgIHrm+eef/9SnPpWJkgAAACDW0h/gX3rppbvuuisajx49evHixVu3br355ptTr8zLy7viiiseeuihZcuWve1tb4uevOOOO1asWJH2qgAAACDW0h/gFy1aFA0GDRr0zDPPzJ07d7e3HHnkkY8//viECRNCCIlE4qc//WnaqwIAAIBYS3+A//Of/xwNrrzyyilTpuzhXcXFxddcc000fuKJJ9JeFQAAAMRa+gP8xo0bo8GJJ564VzfOmjUr6R0AAACASPoDfG1tbTSYPHnyXt04fvz4aFBZWZnekgAAACDu0h/gDzrooGiwY8eOvbqxtLQ06R0AAACASPoD/KGHHhoNHnjggb26sf36Qw45JM01AQAAQMylP8C///3vjwY/+MEP9nw3+5YtW37wgx9E4/e9731prwoAAABiLf0B/kMf+lBxcXEIobKy8qSTTnrhhRd2e8vq1avnzJlTUVERQhgwYMAFF1yQ9qoAAAAg1tIf4CdMmPC1r30tGq9fv/7YY4+dPXv2b37zm9TWdPX19c8888z8+fOnT5++atWq6MnPfvazU6dOTXtVAAAAEGv5mXjTK6+8cvXq1YsWLYoePvnkk08++WQIYfDgwRMmTBg3blxlZeWmTZt27tyZdONpp532rW99KxMlAQAAQKxlJMDn5OT85Cc/OfTQQ//rv/6rsbGx/fmamppVq1a1T7YnueSSSxYuXFhQUJCJkgAAACDW0r+EPpKTk3P11VcvX7784x//+JAhQ3qqIDf3jDPOeOyxx37yk58UFRVlqB4AAACItYzMwLc7/PDDb7nllgULFvz1r3999tlnV61aVVFRUVlZWVhYOHz48IkTJx533HEnnHDCuHHjMloGAAAAxF1mA3xk0KBBJ5988sknn3wAPgsAAAD6pEwtoQcAAADS6EDMwHenqqpq1apVb7zxRklJyVve8hbt6wAAAKA7GQzwiUTi73//+7PPPjthwoQzzzyz40vV1dXXXHPND3/4w7a2tuiZ4cOHf/rTn77mmmsGDhyYuZIgFhpbWgfm52W7CgAAoHfJVIB/6qmnPvWpT7388sshhIsvvrhjgG9ra/s//+f/PP300x2vr6io+MY3vvGXv/zlgQceKCwszFBV0MutLa267r5l67dVjR5aNP99044/fGy2KwIAAHqLjOyBf/DBB0855ZQovae68cYbk9J7u0cfffSaa67JREnQ+7W0tn3tV8+v31YVQthRVf+txS9uq6jPdlEAAEBvkf4AX1VV9Z//+Z9NTU1dvtra2nrddddF40GDBt10003Lly//xS9+cfjhh0dPLly48I033kh7VdD7rXqjcmdVQ/vDppa259Zsz2I9AABAr5L+AP/zn/98+/Z/po7Zs2c//vjjN910U/urjz/++LZt26LxN7/5zfnz50+fPv38889/4oknxowZE0JoaWm5++67014V9H47q5Ln27dXmoEHAAD+Kf0B/s9//nM0mDVr1qOPPjp79uzBgwe3v/qb3/wmGhQWFl566aXtz5eUlFxyySXR+KWXXkp7VdD7ldU0Jj2zIyXSAwAA/Vb6A/y6deuiwZVXXpmbm/z+jzzySDSYM2dOx2AfQnjve98bDTZs2JD2qqD3K69uSHrGDDwAANAugwH+6KOPTnppy5Yta9asicZz5sxJenXSpEnRQICnfypPmYHfXpkc6QEAgH4r/QG+vX1dcXFx0kuPP/54+/jkk09OenXAgAHRoLy8PO1VQe+XGuDLqhta2hJZKQYAAOht0h/gp0yZEg1ef/31pJfuu+++aDB69OgZM2Ykvdre+m7ixIlprwp6v7Ka5Pn2tkQidV09AADQP2UwwC9durTj85WVle3PzJ07NycnJ+nGJ598MhocfPDBaa8Ker/y6uQZ+GAbPAAA8C/pD/AzZ86MBrfccsuKFSvan//qV79aU1MTjc8999yku3bu3HnzzTdHYwGefqi5ta22oTn1eQEeAACIpD/AX3TRRfn5+SGE6urqE0444Qtf+MKPf/zj888/v/00+PHjx5944ont15eXl//qV7869thj169fHz1z6qmnpr0q6OXKqxu73Oy+TYAHAABCCCHkp/0dDz744Kuuuurb3/52CKGqquqGG25IumDhwoV5eXnRePny5W95y1va2traX508efIHPvCBtFcFvVx5ygb4yI4qe+ABAIAQMjEDH0L4r//6rw996ENdvnThhReec8457Q+bm5s7pvdBgwbdcccdhYWFmagKerPUFvSRHWbgAQCAEEKGAnxeXt6dd9559913H3/88VGzuoKCgqOOOuqOO+644447urvrbW972+OPP/7ud787EyVBL1fWTYDfXiXAAwAAIWRiCX27efPmzZs3r6mpqby8fPTo0e3L5jsaNWrUpz/96UMOOeSkk056y1vektqaPoSwZcuWEMKECRMyVypkXXfHxW2rEOABAIAQMhrgIwUFBSUlJd29Onny5IULF/b8DpMnT25paUkkuuzwBX1Ed0vo65taahqaBxcOOMD1AAAAvU1GltADe6u7JnbBNngAACCEIMBDL9HdDHwIYbtG9AAAgAAPvUR5dfcB3gw8AAAgwENv0NqWqKxr6u7VHRrRAwAAAjz0BhW1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t729vaWlRZZlbQuuvXv3vv3227t27XK5XFartaioqLKy8qKLLtLW2+/evfvOO+8UQjz66KPl5eUHDhx47bXX9uzZ09HRkZmZWV5eftZZZ41Xly9gov35z39WHlxxxRUnn3zyiM9fuHDhhRde+Prrr8uy/MILL2h7aHs8nn/84x8bNmyor6/v6+ubMmXK1KlTV65cecYZZ/h/KJ588slXX33V/5JHHnnkkUceUY6zwwWG5nQ6v/jFL/7iF7+QZfmXv/zlI488kpKSMqrP4PP51q9fv2HDhtra2s7OTrvdnp+fv2DBggsvvDDwp+PZZ5994YUXhBBf+MIXrrzyypCf6mc/+9n69euFEN/61rfOPPPM2P9WQELl5eVddNFFa9asEUK8+eabX/rSl7TPif4qzi+adyvEAQEemHT8u3BdLlfkZ95zzz0DAwNCCFWAd7vdv/rVr5SrHMXQ0FBPT8+BAwdeeeWVz3zmM1dffXXIT6gEmOeee06WZf85uFyujz76aN26dd/97ncjTxICEq61tXXHjh1CiNTU1NWrV0f5qiuuuOKNN97wer0bNmzo7+9PS0vzf6ihoeGBBx44fvy4/8ixY8eOHTu2efPmV1555Y477sjLyxvfvwKgN+eee+4777yzY8eOhoaGF1544Zprron+tU1NTQ888EBgbUtPT09PT09tbe3f/va3a6+91v9zunLlSiXAb9iwIWSAd7vd//73v4UQaWlpy5cvH9NfCUi0s88+WwnwyntWoNiu4ni30g8CPDDpTJ06VXnwl7/85ZRTTlFqF0MKOYBEluX77rtPeT8wm83z588vKytzu90HDx48cOCAz+d7/vnnu7q6vvzlL2tf++abb65bty4rK+uaa66prKxMTU3dv3//2rVrDx48uGfPnnvuuefhhx+myxf0bPv27cqDJUuWRPjZUcnLy6uurt66davX6929e7e/e3Bzc/Ptt9+uNA12Op1z586dNm1ac3Pz5s2b+/v7Dx48+PDDD//whz80m82XX375Oeecs3fv3l//+msF/csAAB2WSURBVNdCiGuuuUb5JLm5ueP/lwTi7qtf/epXv/rVoaGhv/71rytWrIhy/FVHR8dtt93W0dEhhLDb7SeffHJ5eXlHR8f+/fsbGxuHh4efeuopn893+eWXCyFKSkpKS0vr6uoOHTrU0tKiXWbcsmWLcs/6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3vCvDEwu/jZyW7ZsGXET7+HDh5UH/tlyc+bMUR5EaDX34YcfvvHGG2+99Za2/9COHTvClW/532n8XwLQIUmSPvvZzyqPn3zyyQj3pPwaGhr++Mc/Ko+vvvpq/3GlUZDX662pqQn5wscff3z16tWrV68OORICSGI2m+2rX/2q8vi3v/2tf/pDIP+wN395i0pPT4/yVpWZmTl16lT/8czMzIULFwohdu7c2dvb+8EHH/h8PiHEOeecM65/CSBhXC7X66+/rjwObCQR21Uc71Z6Q4AHJheHw6F0pOvp6Xn00UeVq5aQ+vv7X3rpJeWxv+h30aJFSqXi2rVrQ+b/lpaWBx988PHHH9+0aZO2GWlfX9/f/vY37atqamqUBkJ2u125rgJ066yzzlJ+iHp7e++6666GhoYITz58+PA999yjdJFYunRpYIHusmXLlAfPP/+89oVut1uZcT116tSQw36A5FZdXa3sSO/q6vr973+vfYL/J+jll1/2N2oJ9PLLLyu3jE899VTV+9HKlSuFEF6vV1nhF0LMmDEj5Do/YDiDg4MPPfSQ8s2/ePHisrIy/4diu4rj3UpvCPDApHPdddcpv5S3bt36ta99Tbt2Icvy1q1b7777bqXMftq0acrcHSFEenq6MrC9v7//gQceaGxsDHxhW1vbfffdpyzXX3DBBSG/+p///GdVht+6dev999+vPF61alWEdkSAHphMpttvv125TGlubr7llluefvppbX+HlpaW3//+97feequyIlFcXHzLLbcEPmH58uXTpk0TQtTU1PziF79QZlArhoeHf/nLXypXV6eddpr2HPw7e4Ekdv311yt18iFXC4uLi5csWSKE6O7u/t73vqda+nvppZeUe9Bms/myyy5TvXbZsmXKQMfXXntNaUjJ8juSgHL99q1vfUv5rk5LS7vpppsCnxDbVdxY3q0wEaTIMzYBJKU33njj8ccf9/8xLS2tqKiosLBQCOFyuZqamvz3ZbOzs++///7A7YVut/vWW2+tra0VQqSkpCxcuLC4uDglJaWhoWHz5s3KsOuLL774f//3f/0vUWbRCSHy8vKUa6ySkpI5c+akpKQcOHDg0KFDyi+ikpKSn/3sZ/4p2YCetbW1/fCHPzx06JD/SGlpaWFhYXp6em9v7/Hjx48dO+b/0Lx5826//fbMzEzVJzl48OAdd9yhXAzl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",alt:""})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'library(tidyr)\nlibrary(Hmisc)\n\ndata <- left_join(results %>% \n filter(name == "GAD-7") %>%\n mutate(value = as.numeric(parse_number(as.character(value)))) %>%\n group_by(id) %>%\n summarise(average_GAD = mean(value)),\n results %>% \n filter(name == "PIU-SF-6") %>%\n mutate(value = as.numeric(parse_number(as.character(value)))) %>%\n group_by(id) %>%\n summarise(average_PIU = mean(value)),\n by="id")\n'})}),"\n",(0,n.jsx)(e.p,{children:"Now, do a regression fit on the filtered data."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"fit <- lm(average_PIU ~ average_GAD, data = drop_na(data))\n"})}),"\n",(0,n.jsxs)(e.p,{children:["Plot the now-filtered data; you\u2019ll find our sample graph below. (",(0,n.jsx)(e.code,{children:"drop_na()"})," removes rows with one or more NA values.)"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'ggplot(drop_na(data), aes(x = average_GAD, y = average_PIU)) +\n geom_point() + \n geom_smooth(method = \'lm\', formula = y~x) +\n # From https://sejohnston.com/2012/08/09/a-quick-and-easy-function-to-plot-lm-results-in-r/\n labs(title = paste("Adj R2 = ",signif(summary(fit)$adj.r.squared, 5),\n "Intercept =",signif(fit$coef[[1]],5 ),\n " Slope =",signif(fit$coef[[2]], 5),\n " P =",signif(summary(fit)$coef[2,4], 5)),\n x = "Average GAD-7",\n y = "Average PIU-SF-6") + \n theme_minimal(base_size = 12) +\n theme(\n panel.grid.major = element_blank(),\n panel.background = element_blank(),\n axis.line = element_line(colour = "black"),\n axis.title.x = element_text(size = 12))\n'})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{src:"data:image/png;base64,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RQEAAACEAbkdCI9wBPh9+/Zdd911H3/8sRBi+PDhV1xxRRguCgAAACCkyO1AmPU7wF911VV9X+x2u3fu3FlTUxP4R61W+6c//Umr1fb3ogAAAACiBLkdiJR+B/jVq1cP8EqJiX/5y19++MMfDuy3AwAAAIggcjsQceF4hF6v10+YMOF3v/vdSSedFIbLAQAAAFALuR2IHv0O8O+++27fF2u12uzs7OHDh6ekpPT3QgAAAAAihdwORKF+B/jLL788FHMAAAAAiDhyOxDNwtcDDwAAACA6kduBQYEADwAAAMQpcjswuBDgAQAAgPhCbgcGqX4H+F27dgV/1ZNPPjn4kwAAAADoO3I7MNj1O8CfcsopwV/V7/cHfxIAAAAAPSO0A7GER+gBAACAWENuB2JSvwP8mDFjQjEHAAAAgCCR24HY1u8Av3379lDMAQAAAGBgyO1AnOARegAAAGBQIrcD8YYADwAAAAwm5HYgbhHgAQAAgEGA3A5g4AG+rq5u5cqVW7duPXjwYFlZ2ZgxY6644gqz2azicAAAAECcI7cD6DLAAP/kk08+/vjjLper+8HMzMxnn3129uzZagwGAAAAxClCO4DjGkiAf+SRRx577LFjj7e0tNx4441NTU2//OUvgx4MAAAAiC/kdgA963eA//bbb5944onArwsLC2fMmFFWVrZ3796VK1fu379fCPHb3/522rRpJSUlKk8KAACAONbc3Lxq1aovvvjC7XYXFhZedtllZ599dqSHUge5HUAf9TvAL1q0yOfzCSEuuOCCNWvWZGZmBo4/8sgjV1111Ycffuh0Op966qlXXnlF5UkBAPHE7/drNJpITwEgKvj9/gULFjzyyCMdHR1dB+fNm3fxxRf/+c9/Hjp0aARnCwa5HUB/afv7G3bu3CmESEhIeOmll7rSuxAiMzPzpZdeSkhIEEJs3rxZxREBAPFj165dt9xyS0FBgVar1ev1Z5111rPPPqsoSqTnAhBJDz300K9//evu6T1g06ZNP/zhDxsbGyMy1YB9851IDwJg8Ol3gN+zZ48Q4pRTTjnppJOO+mjkyJGnnnqqEKKurk6V4QAAceWVV145/fTT//znP9fX1wsh3G73Z5999otf/OLss88OvKUFIA5t3br197///Yk+ra6uvu+++8I5z4CR2wEEr98B3mazCSFO9Ir78OHDhRBH7U4P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G1FWpVK99NJLlZWVJpNJmld/3Lhx0r4OeR1PnjzZ0I+uo0+fPkePHm3BczT7888/pUP17dvXnuMAAMAs9AAAX7FlyxbpmmpycrJ5hjYbAgMD77nnHun+8KVLl1reaz1ixIiIiIiysjJR3/h5s8jIyM2bN69fv37JkiV79+4tKioKDw/v2LFjWlraM888I40kb6777ruvT58+c+fOPXjw4JkzZ/z9/Tt06DBq1Ki//e1v0krve/fufeutt86fP5+ammqZ2EeNGnXy5Ml33313zZo1Z8+eVavVPXv2nDZt2rhx4wwGgzTkPjo62gVPQQihVqtfe+21J5544ocffli/fv2JEyeKiopqa2vj4+NTU1NHjRo1btw48+r00j38qamp0l8d+Do2pFWrVgkJCf369Rs7duyIESOaPklBvdavXy89YPw8AMBODKEHAMDX5ebmajQaIcR33303btw4d5cDAADqxyR2AAB4uU2bNk2ePHny5MmHDx+ut8M///lP6UHv3r1dWBcAAGgehtADAODl4uPjpUXXtFrtihUr6gwIP3369HvvvSeEuPHGG6Xr8AAAwDNxBR4AAC+XlpbWt29fIcQPP/xw991379y5s7S0tLKy8rfffnv77bfT0tIqKiqEEK+88oq7KwUAALZwDzwAAN7v4sWLt9xyS1ZWVkMdZs+ePXfuXFeWBAAAmosr8AAAeL/Y2NijR4++9957dQbJBwQEpKenr127lvQOAIDn4wo8AAC+RavV5ubmXrlyJSIiQqPRqNVqd1cEAACahAAPAAAAAIAMMIQeAAAAAAAZIMADAAAAACADBHgAAAAAAGSAAA8AAAAAgAwQ4AEAAAAAkAECPAAAAAAAMkCABwAAAABABgjwAAAAAADIAAEeAAAAAAAZIMADAAAAACADBHgAAAAAAGSAAA8AAAAAgAwQ4AEAAAAAkAECPAAAAAAAMkCABwAAAABABgjwAAAAAADIwP8D/hFwhaTQptQAAAAASUVORK5CYII=",alt:""})})]})}function Q(A={}){const{wrapper:e}={...(0,d.R)(),...A.components};return e?(0,n.jsx)(e,{...A,children:(0,n.jsx)(o,{...A})}):o(A)}},28453:(A,e,t)=>{t.d(e,{R:()=>v,x:()=>a});var r=t(96540);const n={},d=r.createContext(n);function v(A){const e=r.useContext(d);return r.useMemo((function(){return"function"==typeof A?A(e):{...e,...A}}),[e,A])}function a(A){let e;return e=A.disableParentContext?"function"==typeof A.components?A.components(n):A.components||n:v(A.components),r.createElement(d.Provider,{value:e},A.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[221],{80239:(A,e,t)=>{t.r(e),t.d(e,{assets:()=>f,contentTitle:()=>a,default:()=>Q,frontMatter:()=>v,metadata:()=>r,toc:()=>g});const r=JSON.parse('{"id":"data_science/r","title":"Preparing to Analyze Your Data in R","description":"If you\'d like to follow along with this tutorial but don\'t have an R development environment set up, consider using RStudio Cloud, a free service from the RStudio team.","source":"@site/docs/09-data_science/05-r.md","sourceDirName":"09-data_science","slug":"/data_science/r","permalink":"/data_science/r","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/05-r.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":5,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Preparing to Analyze Your Data in Python","permalink":"/data_science/python"},"next":{"title":"Cortex Quick Start Guide","permalink":"/data_science/cortex/getting-started"}}');var n=t(74848),d=t(28453);const v={},a="Preparing to Analyze Your Data in R",f={},g=[{value:"Connect to your LAMP server.",id:"connect-to-your-lamp-server",level:2},{value:"Download data from the LAMP server.",id:"download-data-from-the-lamp-server",level:2},{value:"Code Output",id:"code-output",level:3},{value:"Optional: Output the data to a CSV.",id:"optional-output-the-data-to-a-csv",level:2},{value:"Check out all the activities in the study",id:"check-out-all-the-activities-in-the-study",level:2},{value:"Code Output",id:"code-output-1",level:3},{value:"Get number of participants in the study",id:"get-number-of-participants-in-the-study",level:2},{value:"Code Output",id:"code-output-2",level:3},{value:"Get engagement and plot activity histogram",id:"get-engagement-and-plot-activity-histogram",level:2},{value:"Code Output",id:"code-output-3",level:3},{value:"Code Output",id:"code-output-4",level:3},{value:"Get mean and standard deviation for any survey scale",id:"get-mean-and-standard-deviation-for-any-survey-scale",level:2},{value:"Code Output",id:"code-output-5",level:3},{value:"Code Output",id:"code-output-6",level:3},{value:"Plot survey scores over time for an individual participant",id:"plot-survey-scores-over-time-for-an-individual-participant",level:2},{value:"Compare self-reported anxiety with self-reported problematic internet use",id:"compare-self-reported-anxiety-with-self-reported-problematic-internet-use",level:2}];function o(A){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",p:"p",pre:"pre",strong:"strong",...(0,d.R)(),...A.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.header,{children:(0,n.jsx)(e.h1,{id:"preparing-to-analyze-your-data-in-r",children:"Preparing to Analyze Your Data in R"})}),"\n",(0,n.jsxs)(e.p,{children:["If you'd like to follow along with this tutorial but don't have an R development environment set up, ",(0,n.jsxs)(e.strong,{children:["consider using ",(0,n.jsx)(e.a,{href:"https://rstudio.cloud/",children:"RStudio Cloud"}),", a free service"]})," from the RStudio team."]}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.strong,{children:"The majority of the code and directions in this page are now deprecated and integrated in the LAMP API. See 'Preparing to Analyze Your Data in Python' for up-to-date data analysis steps."})}),"\n",(0,n.jsx)(e.h2,{id:"connect-to-your-lamp-server",children:"Connect to your LAMP server."}),"\n",(0,n.jsx)(e.p,{children:"First, install the LAMP client library."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"install.packages(\"devtools\")\ndevtools::install_github('BIDMCDigitalPsychiatry/LAMP-r') \n"})}),"\n",(0,n.jsxs)(e.p,{children:["Then connect to the LAMP API. Your Researcher ID comes from the dashboard at ",(0,n.jsx)(e.code,{children:"dashboard.lamp.digital"}),"."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"library(LAMP)\nLAMP <- LAMP$new('https://api.lamp.digital', 'your_email_here@email.com', 'your_password_here')\nresearcher_id <- \"YOUR_RESEARCHER_ID\"\n"})}),"\n",(0,n.jsx)(e.h2,{id:"download-data-from-the-lamp-server",children:(0,n.jsx)(e.strong,{children:"Download data from the LAMP server."})}),"\n",(0,n.jsx)(e.p,{children:"First, download all Participants and retrieve the ID mapping for all Activities in our Study."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"library(dplyr)\nlibrary(anytime)\nlibrary(data.table)\n\nparticipants <- LAMP$Participant$allByStudy(researcher_id) %>% pull(id)\nactivity_map <- LAMP$Activity$allByStudy(researcher_id) %>% \n dplyr::select(id,name) %>%\n\t\trename(activity = id)\n"})}),"\n",(0,n.jsxs)(e.p,{children:["Now we run some pre-processing to flatten the nested data structure that we receive from the ",(0,n.jsx)(e.code,{children:"ActivityEvent"})," API for each Participant, performed in a loop over all Participants in our Study. Because some entries may be ",(0,n.jsx)(e.code,{children:"null"})," (missing or invalid), we ignore those and flatten the data after converting time stamps from the ",(0,n.jsx)(e.code,{children:"UNIX Epoch"})," standard to the human-readable ",(0,n.jsx)(e.code,{children:"YYYY-MM-DD"})," format. There\u2019s a workaround for excessively-nested survey items as well."]}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.strong,{children:"The below section of code is now deprecated and integrated into the LAMP API."})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'data_list <- list()\nfor (i in 1:length(participants)) {\n tmp <- LAMP$ActivityEvent$allByParticipant(participants[i])\n if (length(tmp) > 0) {\n tmp <- right_join(activity_map %>% select(activity, name), \n jsonlite::flatten(tmp) %>% \n mutate(timestamp = anytime(as.numeric(timestamp)/1000, tz = "America/New_York")) %>%\n rename(activity_duration = duration) %>% \n mutate(id = participants[i]),\n by="activity")\n tmp_event_list <- list()\n for (j in 1:nrow(tmp)) {\n if (length(tmp[j,]$temporal_events[[1]]) > 0) {\n\t\t\t\ttmp_event_list[[j]] <- cbind(tmp[j,], tmp[j,]$temporal_events[[1]], row.names=F) %>% \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdplyr::select(-temporal_events)\n }\n }\n data_list[[i]] <- rbindlist(tmp_event_list, fill = T)\n }\n}\ndata_list[sapply(data_list, is.null)] <- NULL\n'})}),"\n",(0,n.jsxs)(e.p,{children:["Now, we combine the data frames we\u2019ve pre-processed and ensure they follow the proper data format. Once we reorder the columns to include only variables of interest, we can call the ",(0,n.jsx)(e.code,{children:"head()"})," function to preview the data frame. To view all available variables in your data frame, use ",(0,n.jsx)(e.code,{children:"colnames(result_events_mod)"}),".\nSome of the columns we\u2019re selecting tell us about meta information about the Activity (such as whether it\u2019s a survey or game), the individual survey question or game level results, and other optional game data (",(0,n.jsx)(e.code,{children:"static_data"}),", which may include ",(0,n.jsx)(e.code,{children:"NA"})," values). To learn more about what each of these columns contains, represents, and can be used for, please see the ",(0,n.jsx)(e.a,{href:"https://www.notion.so/e1a2115ca5d44f96b458fc90c8d49932"})," help topic."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"result_events <- rbindlist(data_list, fill = T) %>% \n\tmutate(id = as.character(id)) %>% \n\tmutate(activity = as.character(activity)) %>% \n\tmutate(name = as.character(name)) \n\nhead(results)\n"})}),"\n",(0,n.jsx)(e.h3,{id:"code-output",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"id timestamp name item value\n1 U1094374134 2019-12-08 PHQ-8 How often did you feel bad about yourself, or that you were a failure or let your family down? 1\n2 U1094374134 2019-12-08 PHQ-8 How often did have you have trouble concentrating on things such as reading or watching tv? 1\n3 U1094374134 2019-12-08 PHQ-8 How often did you find yourself moving so slowly, or so fidgety/restless, that others noticed? 1\n4 U1094374134 2019-12-08 PHQ-8 How often did you have trouble falling or staying asleep, or sleep for more hours than you meant to? 1\n5 U1094374134 2019-12-08 PHQ-8 How often did you feel tired or like you had little energy? 1\n6 U1094374134 2019-12-08 PHQ-8 How often did you find yourself with no appetite, or eating more than you meant to? 1\n"})}),"\n",(0,n.jsxs)(e.h2,{id:"optional-output-the-data-to-a-csv",children:["Optional: ",(0,n.jsx)(e.strong,{children:"Output the data to a CSV."})]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'write.csv(results, "./output-1-27-20.csv", row.names = F)\n'})}),"\n",(0,n.jsx)(e.h1,{id:"appendix-sample-analyses",children:(0,n.jsx)(e.strong,{children:"Appendix: Sample Analyses"})}),"\n",(0,n.jsx)(e.h2,{id:"check-out-all-the-activities-in-the-study",children:"Check out all the activities in the study"}),"\n",(0,n.jsx)(e.p,{children:"This includes both default activities and custom activities."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"activity_map %>% select(activity, spec, name)\n"})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-1",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"## activity spec name\n## 1 QWN0aXZpdHk6MDoxMDM6MjM~ lamp.group Daily Survey Check-In\n## 2 QWN0aXZpdHk6MToxMDM6MzIw lamp.survey PHQ-8\n## 3 QWN0aXZpdHk6MToxMDM6MzQx lamp.survey Instructions\n## 4 QWN0aXZpdHk6MToxMDM6MzQy lamp.survey GAD-7\n## 5 QWN0aXZpdHk6MToxMDM6MzQz lamp.survey PIU-SF-6\n## 6 QWN0aXZpdHk6MToxMDM6MzQ0 lamp.survey Warning\n## 7 QWN0aXZpdHk6MToxMDM6MzQ1 lamp.survey Qualitative Digital Media Use Assessment\n## 8 QWN0aXZpdHk6MToxMDM6MzQ2 lamp.survey Screen Time Use - iPhones only\n## 9 QWN0aXZpdHk6MToxMDM6MzQ3 lamp.survey iPhone/Android Assessment\n## 10 QWN0aXZpdHk6MjoxMDM6MA~~ lamp.nback N-Back\n## 11 QWN0aXZpdHk6MzoxMDM6MA~~ lamp.trails_b Trails B\n## 12 QWN0aXZpdHk6NDoxMDM6MA~~ lamp.spatial_span Spatial Span\n## 13 QWN0aXZpdHk6NToxMDM6MA~~ lamp.simple_memory Simple Memory\n## 14 QWN0aXZpdHk6NjoxMDM6MA~~ lamp.serial7s Serial 7s\n## 15 QWN0aXZpdHk6NzoxMDM6MA~~ lamp.cats_and_dogs Cats and Dogs\n## 16 QWN0aXZpdHk6ODoxMDM6MA~~ lamp.3d_figure_copy 3D Figure Copy\n## 17 QWN0aXZpdHk6OToxMDM6MA~~ lamp.visual_association Visual Association\n## 18 QWN0aXZpdHk6MTA6MTAzOjA~ lamp.digit_span Digit Span\n## 19 QWN0aXZpdHk6MTE6MTAzOjA~ lamp.cats_and_dogs_new Cats and Dogs New\n## 20 QWN0aXZpdHk6MTI6MTAzOjA~ lamp.temporal_order Temporal Order\n## 21 QWN0aXZpdHk6MTM6MTAzOjA~ lamp.nback_new N-Back New\n## 22 QWN0aXZpdHk6MTQ6MTAzOjA~ lamp.trails_b_new Trails B New\n## 23 QWN0aXZpdHk6MTU6MTAzOjA~ lamp.trails_b_dot_touch Trails B Dot Touch\n## 24 QWN0aXZpdHk6MTY6MTAzOjA~ lamp.jewels_a Jewels Trails A\n## 25 QWN0aXZpdHk6MTc6MTAzOjA~ lamp.jewels_b Jewels Trails B\n## 26 QWN0aXZpdHk6MTg6MTAzOjA~ lamp.scratch_image Scratch Image\n## 27 QWN0aXZpdHk6MTk6MTAzOjA~ lamp.spin_wheel Spin Wheel\n"})}),"\n",(0,n.jsx)(e.h2,{id:"get-number-of-participants-in-the-study",children:"Get number of participants in the study"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'print(paste("Number of Participants:", length(participants)))\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-2",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:'## [1] "Number of Participants: 29"\n'})}),"\n",(0,n.jsx)(e.h2,{id:"get-engagement-and-plot-activity-histogram",children:"Get engagement and plot activity histogram"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'engagement_data <- inner_join(results %>% dplyr::count(id), \n results %>% group_by(id) %>% filter(row_number()==n()) %>% select(id, timestamp), \n by="id") %>% \n rename(activities.completed = n) %>% rename(most.recent.activity = timestamp)\n\nengagement_data\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-3",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"## # A tibble: 27 x 3\n## id activities.completed most.recent.activity\n## \n## 1 U1005979819 659 2019-11-16 22:50:57 \n## 2 U1094374134 2085 2019-08-14 12:23:15 \n## 3 U1126469507 503 2019-12-10 21:52:20 \n## 4 U1232915366 226 2020-01-29 00:51:34 \n## 5 U1235780769 767 2019-12-09 20:08:02 \n## 6 U1367615199 813 2019-11-13 16:11:09 \n## 7 U1500960001 742 2019-10-25 21:26:24 \n## 8 U1680931766 1070 2019-12-13 22:41:58 \n## 9 U176381486 585 2019-11-08 18:45:24 \n## 10 U2127860149 170 2019-11-13 16:51:52 \n## # \u2026 with 17 more rows\n"})}),"\n",(0,n.jsx)(e.p,{children:"Let's view a histogram representation of the data."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"hist(engagement_data$activities.completed, breaks=15)\n"})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-4",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.p,{children:"![../Topics/Preparing to analyze your data in R/Untitled.png](../Topics/Preparing to analyze your data in R/Untitled.png)"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{src:"data:image/png;base64,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",alt:""})}),"\n",(0,n.jsx)(e.h2,{id:"get-mean-and-standard-deviation-for-any-survey-scale",children:"Get mean and standard deviation for any survey scale"}),"\n",(0,n.jsxs)(e.p,{children:["We\u2019ll include only anxiety survey (",(0,n.jsx)(e.code,{children:"GAD-7"}),") results and parse/convert their answer data to numbers using the ",(0,n.jsx)(e.code,{children:"readr"})," library. Then, we aggregate by timestamp (which is unique to each Activity), and summarize the table."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'library(readr)\n\ndata <- results %>% \n filter(name == "GAD-7") %>% \n mutate(value = as.numeric(parse_number(as.character(value)))) %>%\n group_by(id,timestamp) %>%\n summarise(average_GAD = mean(value))\n\nsummary(data$average_GAD)\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-5",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"## Min. 1st Qu. Median Mean 3rd Qu. Max. \n## 0.0000 0.4286 0.8571 0.9139 1.4286 3.0000\n"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'print(paste("Mean GAD-7 across all participants:", round(mean(data$average_GAD), 3), "\xb1", round(sd(data$average_GAD), 3)))\n'})}),"\n",(0,n.jsx)(e.h3,{id:"code-output-6",children:(0,n.jsx)(e.code,{children:"Code Output"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:'## [1] "Mean GAD-7 across all participants: 0.914 \xb1 0.667"\n'})}),"\n",(0,n.jsx)(e.h2,{id:"plot-survey-scores-over-time-for-an-individual-participant",children:"Plot survey scores over time for an individual participant"}),"\n",(0,n.jsxs)(e.p,{children:["Filter the first Participant\u2019s mood (",(0,n.jsx)(e.code,{children:"PHQ-8"}),") results and parse the strings into numbers as they may be either numeric or text. Then, we aggregate by timestamp, which is unique for each Activity, and take the mean of all scores for a given timestamp."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'data <- results %>% \n filter(id == participants[1] & name == "PHQ-8") %>%\n mutate(value = as.numeric(as.character(value))) %>%\n group_by(timestamp) %>%\n summarise(average_score = mean(value))\n'})}),"\n",(0,n.jsxs)(e.p,{children:["Plot the now-filtered data using the ",(0,n.jsx)(e.code,{children:"ggplot2"})," library; you\u2019ll find our sample graph below."]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'library(ggplot2)\nggplot(data, aes(x = timestamp, y = average_score)) +\n geom_line(size=1, color="steelblue") +\n theme_minimal(base_size = 15) +\n ylim(0,4) +\n theme(\n panel.grid.major = element_blank(),\n panel.background = element_blank(),\n axis.line = element_line(colour = "black"),\n axis.title.x = element_text(size = 15))\n'})}),"\n",(0,n.jsx)(e.h2,{id:"compare-self-reported-anxiety-with-self-reported-problematic-internet-use",children:"Compare self-reported anxiety with self-reported problematic internet use"}),"\n",(0,n.jsxs)(e.p,{children:["First, we filter data, using a left-join (which is like a merge operation) between the ",(0,n.jsx)(e.code,{children:"GAD-7"})," and ",(0,n.jsx)(e.code,{children:"PIU-6"})," survey instruments, such that each participant is a single row. All answer data is converted to numeric values first, and then we aggregate by ID, which is unique to each Activity. Finally, we take the mean of all scores for a given timestamp."]}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{src:"data:image/png;base64,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AIgBAR4AAABiQIAHAACAGBDgAQAAIAYEeAAAAIgBAR4AAABiQIAHAACAGBDgAQAAIAYEeAAAAIgBAR4AAABiQIAHAACAGBDgAQAAIAbyD8zHVFdX/+1vf9u6dWt1dXV1dfWYMWMuvPDC6KVEIpGTk3NgygAAAICYymyAr66uvuGGG5YsWbJy5cq2trb250855ZQowNfW1k6dOvWMM8743Oc+N23atIwWAwAAAPGVwSX0ixYtmjp16rXXXvvyyy93TO9JSktLb7vttunTp1911VXNzc2ZqwcAAADiK1MBfsGCBZdccsn27dv38PpEInHdddddcMEFra2tGSoJAAAA4isjAf6uu+664oor2h9OnTp1wYIFf/rTn954442kKwsLCy+//PLi4uLo4T333HP99ddnoiQAAACItfQH+Obm5i9/+cvROD8///vf//7KlSsvv/zyOXPmjBs3LunivLy8BQsWrF27dubMmdEz1157bVlZWdqrAgAAgFhLf4C/++67N23aFI2vu+66K6+8sqCgoOdbxo4d++ijj44ePTqEUF9f/7Of/SztVQEAAECspT/A33vvvdEg6i2/h3eNHDly/vz50fiRRx5Je1UAAAAQa+kP8GvWrIkGn/jEJ/bqxjlz5kSD5cuXp7kmAAAAiLn0B/h169ZFg6OOOmqvbpw0aVI0sAceAAAAkqQ/wA8YMCAaNDU17dWNpaWl0WDgwIFprgkAAABiLv0Bvr3V/HPPPbdXN7avnB87dmyaawIAAICYS3+AP+GEE6LBDTfc0NDQsOc3PvDAA9Fg1qxZaa8KAAAAYi39Af7cc8+NBsuXL//Upz61h3fde++9v/vd76LxmWeemfaqAAAAINbSH+BPPfXU97znPdH49ttvP/3001evXt3D9YlEYtGiRfPmzYseTpky5Zxzzkl7VQAAABBr+Zl401tvvfWd73znrl27QghLly59+OGHzzzzzOOOO+7YY4+NLmhqalq7du3mzZuffvrpO++885VXXomez83NvemmmwoKCjJRFQAAAMRXRgL8kUce+fDDD5922mnRgXDNzc1LlixZsmRJ+wVPPvnk1KlTk+7Kycm55ZZb3ve+92WiJAAAAIi19C+hj8yaNWvFihVz587dw+sPPvjgRx555NJLL81QPQAAABBrmQrwIYSSkpLFixe//PLLn/70p6dMmdLlNYWFhbNnz77jjjtWr1590kknZa4YAAAAiLWMLKHv6Jhjjlm4cOHChQvLyspWrFhRXl5eUVGRl5c3YsSIcePGzZgxw453AAAA2K2MB/h2o0aNmj179gH7OAAAAOhL0r+E/uabb54+ffr06dPf9ra3pf3NAQAAoH9K/wz82rVrV6xYEY3r6+uLiorS/hEAAADQ36R/Bv7QQw9tH7cf8A4AAADsj/QH+Llz5w4aNCgaL126NO3vDwAAAP1Q+gP8hAkTvvOd70Tjm266qaysLO0fAQAAAP1NRs6B/8xnPvO9730vJydnx44dp59++ubNmzPxKQAAANB/ZOoYuauuumrWrFkXX3zxs88+e9RRR51//vnvfOc7J0yYMGHChGHDhuXk5PRw74QJEzJUFQAAAMRURgL89OnTo0Fubm4Ioaam5rbbbrvtttv28PZEIpGJqgAAACC+MhLg24+RAwAAANIiI3vgAQAAgPTKyAz8Cy+8kIm3BQAAgH4rIwF+1qxZmXhbAAAA6LcsoQcAAIAYyNQxcv1Bc3Pzzp07s11FP1JRUZHtEiBm6uvr6+vrs10FxFhtbW1tbW22q4AY8y8RpBo1alTPB6v34MAF+A0bNqxfv76ysrKysnLQoEEjRoyYOHHiEUccsc+lAwAAQP+R2QDf2tq6dOnS22+//amnniorK0u9YNiwYSeccMIll1xy5pln5ufHbDnAgAEDDjrooGxX0S9UVlY2NzcPHz48dl8kkC0NDQ01NTVFRUXFxcXZrgViqb6+vra2tri4uKioKNu1QCw1NjZWV1f7lwjSK4N74J966qlp06a9//3v/93vftdleg8hVFZWLl26dO7cuUcfffRf/vKXzBUDAAAAsZapAP/jH/949uzZq1at2sPrX3vttfe85z233357huoBAACAWMvIguT777//sssuSyQS0cOioqLTTz/9He94x6RJkyZOnDhu3LiysrKNGzdu3Ljx2Wefve+++6LOFm1tbR/72McmTJhw2mmnZaIqAAAAiK/0B/iGhoZPf/rTbW1t0cNPfOIT3/jGN5L2ik+ePLn9rPiysrKrr776xz/+cQihtbV1/vz5K1euLCgoSHthAAAAEF/pX0L/61//euPGjdF4wYIF//M//9Nzp7dRo0bdeuut3/ve96KHa9asueeee9JeFQAAAMRa+gP873//+2hwyimnXH755Xt411VXXXXyySdH4/vvvz/tVQEAAECspT/Av/TSS9Hg4x//+F7d+IlPfCLpHQAAAIBI+gP8tm3bosH06dP36sY3v/nN0aC0tDTNNQEAAEDMpT/ANzc3R4MBAwbs1Y3tjeva3wEAAACIpD/AjxkzJhqsXr16r25sv37s2LFprgkAAABiLv0B/sgjj4wGP//5z/fqxjvvvDPpHQAAAIBI+gP8mWeeGQ1+8YtfPPDAA3t41x//+Mf2wH/GGWekvSoAAACItfQH+Hnz5o0YMSKEkEgk5s6d+8Mf/rCtra2H69va2n7yk5+cddZZiUQihDBixIjzzz8/7VUBAABArKU/wI8aNeqb3/xmNG5qapo/f/60adO+853vPP744+vWrWtqaoqeX79+/RNPPPH9739/xowZH/vYxxobG6NbvvnNb44cOTLtVQEAAECs5WfiTT/5yU+uWbPmxhtvjB6++uqrV199dTTOyckZNmxYZWVlNN+e5LOf/ewnP/nJTJQEAAAAsZb+GfjIggULbrnlliFDhiQ9n0gkKioqUtP74MGDf/jDH7ZnfgAAAKCjTAX4EMLHP/7xVatWXXvttZMnT+7hskMOOeTrX//6qlWrPvnJT+bk5GSuHgAAAIivjCyhbzdu3Livfe1rX/va1zZt2vT888+//vrrFRUVNTU1gwcPHjZs2MEHH3zssccefPDBGa0BAAAA+oDMBvh2kyZNmjRp0oH5LAAAAOh7MriEfk/0fMIcAAAAEMlsgC8vL//Zz3720Y9+9Jxzzkl9tba2tri4eObMmV/60pdWrlyZ0UoAAAAg1jK1hL6xsfEb3/jGggUL6uvrQwgTJ07s8rKGhobly5cvX778uuuu+8hHPvLf//3fgwYNylBJAAAAEF8ZCfDV1dWnn376U089tee3tLW13XbbbcuWLXvssceKi4szURUAAADEV0aW0F922WUd03tJSclZZ52VellhYeH111//3ve+t6CgIHrm+eef/9SnPpWJkgAAACDW0h/gX3rppbvuuisajx49evHixVu3br355ptTr8zLy7viiiseeuihZcuWve1tb4uevOOOO1asWJH2qgAAACDW0h/gFy1aFA0GDRr0zDPPzJ07d7e3HHnkkY8//viECRNCCIlE4qc//WnaqwIAAIBYS3+A//Of/xwNrrzyyilTpuzhXcXFxddcc000fuKJJ9JeFQAAAMRa+gP8xo0bo8GJJ564VzfOmjUr6R0AAACASPoDfG1tbTSYPHnyXt04fvz4aFBZWZnekgAAACDu0h/gDzrooGiwY8eOvbqxtLQ06R0AAACASPoD/KGHHhoNHnjggb26sf36Qw45JM01AQAAQMylP8C///3vjwY/+MEP9nw3+5YtW37wgx9E4/e9731prwoAAABiLf0B/kMf+lBxcXEIobKy8qSTTnrhhRd2e8vq1avnzJlTUVERQhgwYMAFF1yQ9qoAAAAg1tIf4CdMmPC1r30tGq9fv/7YY4+dPXv2b37zm9TWdPX19c8888z8+fOnT5++atWq6MnPfvazU6dOTXtVAAAAEGv5mXjTK6+8cvXq1YsWLYoePvnkk08++WQIYfDgwRMmTBg3blxlZeWmTZt27tyZdONpp532rW99KxMlAQAAQKxlJMDn5OT85Cc/OfTQQ//rv/6rsbGx/fmamppVq1a1T7YnueSSSxYuXFhQUJCJkgAAACDW0r+EPpKTk3P11VcvX7784x//+JAhQ3qqIDf3jDPOeOyxx37yk58UFRVlqB4AAACItYzMwLc7/PDDb7nllgULFvz1r3999tlnV61aVVFRUVlZWVhYOHz48IkTJx533HEnnHDCuHHjMloGAAAAxF1mA3xk0KBBJ5988sknn3wAPgsAAAD6pEwtoQcAAADS6EDMwHenqqpq1apVb7zxRklJyVve8hbt6wAAAKA7GQzwiUTi73//+7PPPjthwoQzzzyz40vV1dXXXHPND3/4w7a2tuiZ4cOHf/rTn77mmmsGDhyYuZIgFhpbWgfm52W7CgAAoHfJVIB/6qmnPvWpT7388sshhIsvvrhjgG9ra/s//+f/PP300x2vr6io+MY3vvGXv/zlgQceKCwszFBV0MutLa267r5l67dVjR5aNP99044/fGy2KwIAAHqLjOyBf/DBB0855ZQovae68cYbk9J7u0cfffSaa67JREnQ+7W0tn3tV8+v31YVQthRVf+txS9uq6jPdlEAAEBvkf4AX1VV9Z//+Z9NTU1dvtra2nrddddF40GDBt10003Lly//xS9+cfjhh0dPLly48I033kh7VdD7rXqjcmdVQ/vDppa259Zsz2I9AABAr5L+AP/zn/98+/Z/po7Zs2c//vjjN910U/urjz/++LZt26LxN7/5zfnz50+fPv38889/4oknxowZE0JoaWm5++67014V9H47q5Ln27dXmoEHAAD+Kf0B/s9//nM0mDVr1qOPPjp79uzBgwe3v/qb3/wmGhQWFl566aXtz5eUlFxyySXR+KWXXkp7VdD7ldU0Jj2zIyXSAwAA/Vb6A/y6deuiwZVXXpmbm/z+jzzySDSYM2dOx2AfQnjve98bDTZs2JD2qqD3K69uSHrGDDwAANAugwH+6KOPTnppy5Yta9asicZz5sxJenXSpEnRQICnfypPmYHfXpkc6QEAgH4r/QG+vX1dcXFx0kuPP/54+/jkk09OenXAgAHRoLy8PO1VQe+XGuDLqhta2hJZKQYAAOht0h/gp0yZEg1ef/31pJfuu+++aDB69OgZM2Ykvdre+m7ixIlprwp6v7Ka5Pn2tkQidV09AADQP2UwwC9durTj85WVle3PzJ07NycnJ+nGJ598MhocfPDBaa8Ker/y6uQZ+GAbPAAA8C/pD/AzZ86MBrfccsuKFSvan//qV79aU1MTjc8999yku3bu3HnzzTdHYwGefqi5ta22oTn1eQEeAACIpD/AX3TRRfn5+SGE6urqE0444Qtf+MKPf/zj888/v/00+PHjx5944ont15eXl//qV7869thj169fHz1z6qmnpr0q6OXKqxu73Oy+TYAHAABCCCHkp/0dDz744Kuuuurb3/52CKGqquqGG25IumDhwoV5eXnRePny5W95y1va2traX508efIHPvCBtFcFvVx5ygb4yI4qe+ABAIAQMjEDH0L4r//6rw996ENdvnThhReec8457Q+bm5s7pvdBgwbdcccdhYWFmagKerPUFvSRHWbgAQCAEEKGAnxeXt6dd9559913H3/88VGzuoKCgqOOOuqOO+644447urvrbW972+OPP/7ud787EyVBL1fWTYDfXiXAAwAAIWRiCX27efPmzZs3r6mpqby8fPTo0e3L5jsaNWrUpz/96UMOOeSkk056y1vektqaPoSwZcuWEMKECRMyVypkXXfHxW2rEOABAIAQMhrgIwUFBSUlJd29Onny5IULF/b8DpMnT25paUkkuuzwBX1Ed0vo65taahqaBxcOOMD1AAAAvU1GltADe6u7JnbBNngAACCEIMBDL9HdDHwIYbtG9AAAgAAPvUR5dfcB3gw8AAAgwENv0NqWqKxr6u7VHRrRAwAAAjz0BhW1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t729vaWlRZZlbQuuvXv3vv3227t27XK5XFartaioqLKy8qKLLtLW2+/evfvOO+8UQjz66KPl5eUHDhx47bXX9uzZ09HRkZmZWV5eftZZZ41Xly9gov35z39WHlxxxRUnn3zyiM9fuHDhhRde+Prrr8uy/MILL2h7aHs8nn/84x8bNmyor6/v6+ubMmXK1KlTV65cecYZZ/h/KJ588slXX33V/5JHHnnkkUceUY6zwwWG5nQ6v/jFL/7iF7+QZfmXv/zlI488kpKSMqrP4PP51q9fv2HDhtra2s7OTrvdnp+fv2DBggsvvDDwp+PZZ5994YUXhBBf+MIXrrzyypCf6mc/+9n69euFEN/61rfOPPPM2P9WQELl5eVddNFFa9asEUK8+eabX/rSl7TPif4qzi+adyvEAQEemHT8u3BdLlfkZ95zzz0DAwNCCFWAd7vdv/rVr5SrHMXQ0FBPT8+BAwdeeeWVz3zmM1dffXXIT6gEmOeee06WZf85uFyujz76aN26dd/97ncjTxICEq61tXXHjh1CiNTU1NWrV0f5qiuuuOKNN97wer0bNmzo7+9PS0vzf6ihoeGBBx44fvy4/8ixY8eOHTu2efPmV1555Y477sjLyxvfvwKgN+eee+4777yzY8eOhoaGF1544Zprron+tU1NTQ888EBgbUtPT09PT09tbe3f/va3a6+91v9zunLlSiXAb9iwIWSAd7vd//73v4UQaWlpy5cvH9NfCUi0s88+WwnwyntWoNiu4ni30g8CPDDpTJ06VXnwl7/85ZRTTlFqF0MKOYBEluX77rtPeT8wm83z588vKytzu90HDx48cOCAz+d7/vnnu7q6vvzlL2tf++abb65bty4rK+uaa66prKxMTU3dv3//2rVrDx48uGfPnnvuuefhhx+myxf0bPv27cqDJUuWRPjZUcnLy6uurt66davX6929e7e/e3Bzc/Ptt9+uNA12Op1z586dNm1ac3Pz5s2b+/v7Dx48+PDDD//whz80m82XX375Oeecs3fv3l//+msF/csAAB2WSURBVNdCiGuuuUb5JLm5ueP/lwTi7qtf/epXv/rVoaGhv/71rytWrIhy/FVHR8dtt93W0dEhhLDb7SeffHJ5eXlHR8f+/fsbGxuHh4efeuopn893+eWXCyFKSkpKS0vr6uoOHTrU0tKiXWbcsmWLcs/6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3vCvDEwu/jZyW7ZsGXET7+HDh5UH/tlyc+bMUR5EaDX34YcfvvHGG2+99Za2/9COHTvClW/532n8XwLQIUmSPvvZzyqPn3zyyQj3pPwaGhr++Mc/Ko+vvvpq/3GlUZDX662pqQn5wscff3z16tWrV68OORICSGI2m+2rX/2q8vi3v/2tf/pDIP+wN395i0pPT4/yVpWZmTl16lT/8czMzIULFwohdu7c2dvb+8EHH/h8PiHEOeecM65/CSBhXC7X66+/rjwObCQR21Uc71Z6Q4AHJheHw6F0pOvp6Xn00UeVq5aQ+vv7X3rpJeWxv+h30aJFSqXi2rVrQ+b/lpaWBx988PHHH9+0aZO2GWlfX9/f/vY37atqamqUBkJ2u125rgJ066yzzlJ+iHp7e++6666GhoYITz58+PA999yjdJFYunRpYIHusmXLlAfPP/+89oVut1uZcT116tSQw36A5FZdXa3sSO/q6vr973+vfYL/J+jll1/2N2oJ9PLLLyu3jE899VTV+9HKlSuFEF6vV1nhF0LMmDEj5Do/YDiDg4MPPfSQ8s2/ePHisrIy/4diu4rj3UpvCPDApHPdddcpv5S3bt36ta99Tbt2Icvy1q1b7777bqXMftq0acrcHSFEenq6MrC9v7//gQceaGxsDHxhW1vbfffdpyzXX3DBBSG/+p///GdVht+6dev999+vPF61alWEdkSAHphMpttvv125TGlubr7llluefvppbX+HlpaW3//+97feequyIlFcXHzLLbcEPmH58uXTpk0TQtTU1PziF79QZlArhoeHf/nLXypXV6eddpr2HPw7e4Ekdv311yt18iFXC4uLi5csWSKE6O7u/t73vqda+nvppZeUe9Bms/myyy5TvXbZsmXKQMfXXntNaUjJ8juSgHL99q1vfUv5rk5LS7vpppsCnxDbVdxY3q0wEaTIMzYBJKU33njj8ccf9/8xLS2tqKiosLBQCOFyuZqamvz3ZbOzs++///7A7YVut/vWW2+tra0VQqSkpCxcuLC4uDglJaWhoWHz5s3KsOuLL774f//3f/0vUWbRCSHy8vKUa6ySkpI5c+akpKQcOHDg0KFDyi+ikpKSn/3sZ/4p2YCetbW1/fCHPzx06JD/SGlpaWFhYXp6em9v7/Hjx48dO+b/0Lx5826//fbMzEzVJzl48OAdd9yhXAzl5+dXVlZOmzato6Nj8+bNyk/KjBkzHn74YX9nx5qamjvuuEMIMW3atIsvvthqta5YsSItLW2i/7LAuPvNb36jlPj++Mc/Pvnkk8M9bePGjQ8++KD/j2ecccZ3vvMd/x9dLtfNN9+sNJNPS0urqqoqLy/v7Ozcu3evv3VLuI6tP/7xjz/44APlscVi+b//+78Ic1IAPWhsbLzxxhuFEJmZmcuXLw/8kMfj6erqOnTokH+2gt1uv/vuu/1jgP1iuIoTo3+3woQiwAOT1NatWx977DH/RNCQFi9efOONN2pH7Pb29j700EPbt2/XvsRsNl944YU33HBDYL2iP8DfeOONR48eXbdunfaFs2bN+t73vucfsg3on9vtXrt27dq1a3t7e8M9x+FwXHXVVatWrQrXr76mpuZHP/qR/5Ir0Ny5c7/5zW/6x/8IIfr7+6+//nr/QCwhxJNPPhlhCDagW1EGeCHEj370ow0bNiiPVQFeCHH8+PEHHngg5E6WlJSUa6+9dvXq1SE/beCtgdNOO+3222+P4W8BxJM/wI9o1qxZN910U7g2daO9ilOM6t0KE4pmm8AktWjRot/+9rcf/v/t3XtQVOXjx/GzIqCwKpcQhVAUzAuXASFILQQJBcMLXlLKadR0QMYSQSbHtElTGyfX+4xoRRk5iRqlo0EooOYNA7wF4iiiKAYZIMhFcV2+f5xfZ/YH7AoKyMH3669nz/Ocs88+/LF89jznef7889y5c9evXy8tLa2pqTE0NDQ1NbW1tR08eLCPj4+udX2VSuWqVasyMzOPHTuWl5d3//797t2729jYDBw4cNKkSeKd/CYpFIoFCxaMHDkyKSnpypUrlZWVSqVy4MCBo0eP9vPza/xtAXRkRkZG7777bnBw8Llz57Kzs2/cuFFRUVFVVaVUKs3MzAYNGuTp6enh4WFsbKznIk5OTjt37kxKSsrIyCgqKnr48GGfPn3s7OxGjBghPqarzcTE5LPPPtu1a1dBQYFCoTA3N+d2Bzq9sLAwcbW5JmttbGy2bNmSnp5+5syZ/Pz8yspKY2Nja2trNze38ePH6/l5y9PT08TERHxOmO3f0QmYmpqam5sPGTJk5MiRHh4eev6nerb/4lr0bYU2xR14AG1OugMfERGh69l4AAAAAPqxiB0AAAAAADJAgAcAAAAAQAYI8AAAAAAAyAABHgAAAAAAGSDAAwAAAAAgA6xCDwAAAACADHAHHgAAAAAAGSDAAwAAAAAgAwR4AAAAAABkgAAPAAAAAIAMEOABAAAAAJABAjwAAAAAADJAgAcAAAAAQAYI8AAAAAAAyAABHgAAAAAAGSDAAwAAAAAgAwR4AAAAAABkgAAPAAAAAIAMEOABAGgP8+fPV/wnJibmRXcHAADIDwEeAIDWIUX0oKCgF92XDofBAQDg+RHgAQAAAACQAQI8AAAAAAAy0PVFdwAAgJfCypUrIyMjxbKlpeWL7QwAAJAjAjwAAO3BxsbGxsbmRfcCAADIGFPoAQDocEpLS9evX+/t7W1tbd2tWzd7e/spU6YkJydrt7l79+6qVas8PDysrKxMTEycnZ1DQkIOHTrUnOsfPXo0PDzc2dnZ0tKyR48ebm5uU6dOjY+PV6vVTz23qKho7dq1M2bM8PDwMDMz69279xtvvPH+++/HxsZWVVU94wfWcvr06cjIyPHjxzs7O/fq1cvMzMzZ2TkwMHDRokUnT55s/nXaegwFQcjMzAwLC3N2du7Ro4e5ufmwYcPCw8PT09Nb8GkBAGiRegAA8BzWr1+v53s2Ly9PbJaZmSkdvHPnjvYV/vrrL/G4vb19fX19Wlpanz59mrzaRx99pNFo6uvrf/rpJzMzsybbTJo0qa6uTldv8/LyfH19dfW2X79+u3fv1nWuWq1esWKFoaGhrtP79OmTnJz8DIMjKi4ufuoa9WPHjr13717jvrXDGLq5uYm1J0+erK2tDQsL09XJd955p8GfGACAVsEUegAAOpDjx4+PGzfu8ePHTdZu3brV3t7ewsJi7ty59fX1TbY5cOCASqVaunRp46rs7OyAgICysjJd715YWDhr1qx//vlHelxf2+zZs3/88Uc9nS8uLp40aVJqauqoUaP0NGtSZWXlmDFjcnNz9TdLSUkJCAg4d+6cnt8R2nQMBUFQq9XBwcGpqam6OnD48GEfH59jx47Z2dnp/TQAALSMQtdXFwAAaI59+/bt3LlTEITc3Ny7d+8KgmBpaenu7i7WxsXFiSkuKyvL09NTPHjnzh1bW1vpCjk5Oc7OzoIg9OrVy8DAoKysrEuXLhMmTBg1alTPnj0vXLjw3XffPXr0SGxsZGSkVqs1Go0gCH5+fr6+vra2tjk5OXFxcRUVFWKb7t27l5WVdevWTbufJSUlTk5OpaWl4ksXF5eoqCgvLy9jY+Pc3NzY2NjffvtNavztt9/OnTtX+/Q9e/aEhoaKZaVSGRYWFhQUZG9vX1VVlZOTo1KpsrOzxVpXV9eLFy+2aHAEQViyZIlKpRLLr7zyyscff/zWW2/Z2dnV1dXdvn37wIEDu3btqq6uFhts3749PDxcu3vtMIbu7u4XLlwQBGHUqFGnTp0SD9rY2Pj7+1tYWNy+ffvIkSMPHjyQ2nt6emZkZHTpwuOKAIDW84JnAAAA0FnMmzdP/G4NDAxsXNucKfQia2vr1NRU7Qa5ubkNJnubmprGx8drtyksLOzfv7/U4NKlSw06MHXqVKl2zpw5NTU1DRqoVKquXbtKfXjw4IF27YgRI8Sqnj17Xr58ucG5arXax8dHuv758+dbNDh1dXXSB7SxsSkuLm7c5uzZs927d9d1kXYYQ2kKvcjQ0FClUqnVaqlBdXV1VFSUdptt27Y1/iAAADwzfhUGAKBjSUhIGDNmjPaRoUOHLlu2TPvI1q1bZ82apX3Ezs5uzZo10su8vDzt2pycnJ9//lksBwUFxcXFSWFYEhUVtXbtWrFcUlKi/fh6XV3d2bNnxfK8efPEe93aDAwMVq1aJb3MyMh4yof8/7Kysu7fvy+Wv/rqK2tr68ZtvL29J0+eLJZv3bql/4JtMYYN7NixIyoqysDAQDpiYmKiUqlWr14tHdm0aVM9Ux0BAK2HAA8AQAcyffr00aNHNz7u7+8vlb29vWfPnt24TUBAgFSurKzUrhLnsQuCYGhouHHjRl3vvmjRIkdHR7GcmJgoHS8rK5OC6ODBg5s818PDY/Z/Wrph3s2bN8WCQqHQ/hQNuLq6ioXa2lo9V2ujMdTm6ek5Z86cJquWLVv2+uuvi+Xr16+3aOV8AAD0I8ADANCBjBs3rsnjAwYMkMqBgYEKhaJxm969e5uYmDR5+uHDh8XChAkTdCVwQRCMjIwiIiLEck5OjvREt5WVlZGRkVhOS0tr8lylUvndfyZMmKDrLZo0c+ZMcWagRqOxsrLS1Ux6iF2/NhpDbdHR0bqqFApFTEyM9JIADwBoRQR4AAA6kMaz00VSfhYEwcXFRdfp2s0kpaWl+fn5Ytnb21t/B6S73BqNJisrSywbGBg4ODiI5YSEhMjISD13p9tITU2N9qQAPdpiDLWZmZlNmzZNT4OJEydKqwn8+eef+q8GAEDzEeABAOhAdO1M3tI22rQXeJNmd+sybNgwqfz3339LZe091TZv3vzqq6+Ghobu3r27qKioRZ1pkdra2suXL+/ZsycmJsbR0fHSpUvNOastxlCbg4ODlM+bZGxsLK2u36bjAwB42bAPPAAAnZz2xu8NlnbTT3tTtA8++ODIkSPSPvAPHjzYs2fPnj17BEEYNGiQv7+/+OS59qJuz6Curu7YsWNJSUm5ublXr14tLCzsgIvAaa9Ur4u9vX1BQYEgCOXl5W3fIwDAy4I78AAAdHLSAu8tpR3gBUGIj4/fu3dv3759GzS7du1abGysv7+/ra3thg0bxP3VW0qj0cTGxvbt23fcuHGbNm1KSUm5deuWdno3NTV97bXXnuHKra5fv35PbSOF/AZjCADA8+AOPAAAnZz2XXEfH5+nPuMt6d27d4Mj06dPDwkJSU9P37dv36+//nrv3j3t2pKSkujo6MTExOTkZKVS2fwe1tfXv/feewkJCdoHjY2NXVxcnJychg0b5uTk5Ofnt3379iVLljT/sm2kOWvpVVdXiwVTU9M27g4A4CVCgAcAoJMzNzeXynFxcdJydM+ma9euAQEBAQEBO3bsuHjxYlpaWlpaWmpq6sOHD8UGp06d+vTTTzdv3tz8a6pUKim9m5iYhIeHT5s2bfjw4cbGxs/T1TYibXqnx40bN8SC9uADAPCcmEIPAEAnpz3p/c6dO611WYVC4ebmFhUVdejQoXv37qlUKmkDtm3btjV/6rharZa2pre2ts7JyVGpVCNGjGic3jvI8/C3bt16ahspwDd+4gAAgGdGgAcAoJNzdXWVwvDp06f1N37y5En1f6SDN2/ezMrKysrK0rUOvFKpjIqKWrdunfhSo9Hk5eU1s3tXr169e/euWF61apW9vb2ultqr8b1A+fn5//77r54G58+fl9au8/LyapdOAQBeCgR4AAA6OSMjI2n7d2kZeV1iYmKUSqVSqXR0dJTueG/YsMHT09PT09Pd3V1Pih49erRUljL5UxUWFkpld3d3PS2PHz/ezGu2qUePHm3dulVPgzVr1kjlN998s+17BAB4WRDgAQDo/D788EOxkJubGxcXp6tZSUnJzp07xXJwcLBCoRDL0rrrGo3m6NGjuk7PycmRytbW1s3sm/ae6g1WxdMWHx//1OkD7Wbbtm0VFRVNVl28eDExMVEsDxw4UPtHDQAAnhMBHgCAVlZbW/uiu9DQjBkz7OzsxPLChQsPHjzYuE15eXlgYKA4c16hUERGRkpVfn5+UvmTTz5pcgJ5SUnJ559/LpbNzMyGDx/eZE8aD4725nANFqKXHDp0aN68edJLXeG53ZSVlYWEhFRWVjY4npeXFxwcLM1cWLx4sfQjCAAAz48ADwBA6+jS5f++Vc+fPy+uc6ZWq59tU/RWZ2xs/P3334thsra2dvLkyVOnTo2Li8vMzLx9+/aZM2dWr149dOjQCxcuiO2jo6OdnJyk04cPHy4F8ps3b3p5eW3cuDErK6uwsLCgoODEiRMrVqxwdXW9evWq2GbhwoUNNqvTMzj9+/f38PAQa3/44YcFCxZcu3ZNzMDFxcW///772LFjJ0yYUFdXJ4Xh8vLypUuXXrly5YU8FS92Iz093cnJacOGDdnZ2fn5+cePH1+8eLG7u7u0TKCXl1dERET7dw8A0ImxjRwAAK3D0dFRLFRWVg4cOLBXr14VFRW5ubmDBw9+sR0TjRkzZvv27RERERqNpr6+PjExUZrp3cCUKVPWrl2rfUShUGzfvt3X11e8f15QUBAVFaXrjXx9fZcvX97goP7BWb9+/dtvv/3kyRNBEGJjY2NjYw0NDY2NjauqqqQrODg4fP3112PHjlWr1YIgrFu3bt26dd988430dEC7CQ8PP3Xq1KVLl+7cuRMdHd1kG0dHx/3790s/WwAA0Cr4XgEAoHXMnDnTwsJCLGs0mvLy8va//d6zZ083N7eQkJChQ4c2rg0LCzt48OCAAQN0nd6tW7c1a9bs3bvX0NCwQZWXl1dycnL//v31vHvXrl0jIyOTkpIa7wCnf3B8fX337t1rY2MjHXn8+LGU3g0MDObPn5+RkeHn5/fll1/q6UCr0D+GgiBYWlqmpqZOnDhR1xWCg4NPnDghPbMAAEBrUXSQLVUBAOgEcnJyVq5cmZGRUVJSYmlp2bdv319++aWjBblHjx7t37//4MGD2dnZJSUldXV1FhYWLi4u/v7+c+bMsbKy0nNubW1tYmJiSkpKYWHh7du3i4qKzM3N7e3t7e3t3dzcQkND9XzYpw5OTU3Nli1b/vjjj2vXrhUWFopXDgoKmjlzpvZz8idOnEhISKiurh4yZMj06dMdHBxaZVieyt3dXXzEYPny5V988YUgCCkpKeLSesXFxQYGBjY2Nj4+PqGhodpLBgAA0IoI8AAAAE/XOMADANDOmEIPAAAAAIAMEOABAAAAAJABAjwAAAAAADJAgAcAAAAAQAYI8AAAAAAAyAABHgAAAAAAGSDAAwAAAAAgA+wDDwAAAACADHAHHgAAAAAAGSDAAwAAAAAgAwR4AAAAAABkgAAPAAAAAIAMEOABAAAAAJABAjwAAAAAADJAgAcAAAAAQAYI8AAAAAAAyAABHgAAAAAAGSDAAwAAAAAgAwR4AAAAAABkgAAPAAAAAIAMEOABAAAAAJABAjwAAAAAADJAgAcAAAAAQAYI8AAAAAAAyAABHgAAAAAAGSDAAwAAAAAgAwR4AAAAAABk4H+dN/fPS5KD2wAAAABJRU5ErkJggg==",alt:""})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'library(tidyr)\nlibrary(Hmisc)\n\ndata <- left_join(results %>% \n filter(name == "GAD-7") %>%\n mutate(value = as.numeric(parse_number(as.character(value)))) %>%\n group_by(id) %>%\n summarise(average_GAD = mean(value)),\n results %>% \n filter(name == "PIU-SF-6") %>%\n mutate(value = as.numeric(parse_number(as.character(value)))) %>%\n group_by(id) %>%\n summarise(average_PIU = mean(value)),\n by="id")\n'})}),"\n",(0,n.jsx)(e.p,{children:"Now, do a regression fit on the filtered data."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:"fit <- lm(average_PIU ~ average_GAD, data = drop_na(data))\n"})}),"\n",(0,n.jsxs)(e.p,{children:["Plot the now-filtered data; you\u2019ll find our sample graph below. (",(0,n.jsx)(e.code,{children:"drop_na()"})," removes rows with one or more NA values.)"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-r",children:'ggplot(drop_na(data), aes(x = average_GAD, y = average_PIU)) +\n geom_point() + \n geom_smooth(method = \'lm\', formula = y~x) +\n # From https://sejohnston.com/2012/08/09/a-quick-and-easy-function-to-plot-lm-results-in-r/\n labs(title = paste("Adj R2 = ",signif(summary(fit)$adj.r.squared, 5),\n "Intercept =",signif(fit$coef[[1]],5 ),\n " Slope =",signif(fit$coef[[2]], 5),\n " P =",signif(summary(fit)$coef[2,4], 5)),\n x = "Average GAD-7",\n y = "Average PIU-SF-6") + \n theme_minimal(base_size = 12) +\n theme(\n panel.grid.major = element_blank(),\n panel.background = element_blank(),\n axis.line = element_line(colour = "black"),\n axis.title.x = element_text(size = 12))\n'})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{src:"data:image/png;base64,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RQEAAACEAbkdCI9wBPh9+/Zdd911H3/8sRBi+PDhV1xxRRguCgAAACCkyO1AmPU7wF911VV9X+x2u3fu3FlTUxP4R61W+6c//Umr1fb3ogAAAACiBLkdiJR+B/jVq1cP8EqJiX/5y19++MMfDuy3AwAAAIggcjsQceF4hF6v10+YMOF3v/vdSSedFIbLAQAAAFALuR2IHv0O8O+++27fF2u12uzs7OHDh6ekpPT3QgAAAAAihdwORKF+B/jLL788FHMAAAAAiDhyOxDNwtcDDwAAACA6kduBQYEADwAAAMQpcjswuBDgAQAAgPhCbgcGqX4H+F27dgV/1ZNPPjn4kwAAAADoO3I7MNj1O8CfcsopwV/V7/cHfxIAAAAAPSO0A7GER+gBAACAWENuB2JSvwP8mDFjQjEHAAAAgCCR24HY1u8Av3379lDMAQAAAGBgyO1AnOARegAAAGBQIrcD8YYADwAAAAwm5HYgbhHgAQAAgEGA3A5g4AG+rq5u5cqVW7duPXjwYFlZ2ZgxY6644gqz2azicAAAAECcI7cD6DLAAP/kk08+/vjjLper+8HMzMxnn3129uzZagwGAAAAxClCO4DjGkiAf+SRRx577LFjj7e0tNx4441NTU2//OUvgx4MAAAAiC/kdgA963eA//bbb5944onArwsLC2fMmFFWVrZ3796VK1fu379fCPHb3/522rRpJSUlKk8KAACAONbc3Lxq1aovvvjC7XYXFhZedtllZ599dqSHUge5HUAf9TvAL1q0yOfzCSEuuOCCNWvWZGZmBo4/8sgjV1111Ycffuh0Op966qlXXnlF5UkBAPHE7/drNJpITwEgKvj9/gULFjzyyCMdHR1dB+fNm3fxxRf/+c9/Hjp0aARnCwa5HUB/afv7G3bu3CmESEhIeOmll7rSuxAiMzPzpZdeSkhIEEJs3rxZxREBAPFj165dt9xyS0FBgVar1ev1Z5111rPPPqsoSqTnAhBJDz300K9//evu6T1g06ZNP/zhDxsbGyMy1YB9851IDwJg8Ol3gN+zZ48Q4pRTTjnppJOO+mjkyJGnnnqqEKKurk6V4QAAceWVV145/fTT//znP9fX1wsh3G73Z5999otf/OLss88OvKUFIA5t3br197///Yk+ra6uvu+++8I5z4CR2wEEr98B3mazCSFO9Ir78OHDhRBH7U4P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G1FWpVK99NJLlZWVJpNJmld/3Lhx0r4OeR1PnjzZ0I+uo0+fPkePHm3BczT7888/pUP17dvXnuMAAMAs9AAAX7FlyxbpmmpycrJ5hjYbAgMD77nnHun+8KVLl1reaz1ixIiIiIiysjJR3/h5s8jIyM2bN69fv37JkiV79+4tKioKDw/v2LFjWlraM888I40kb6777ruvT58+c+fOPXjw4JkzZ/z9/Tt06DBq1Ki//e1v0krve/fufeutt86fP5+ammqZ2EeNGnXy5Ml33313zZo1Z8+eVavVPXv2nDZt2rhx4wwGgzTkPjo62gVPQQihVqtfe+21J5544ocffli/fv2JEyeKiopqa2vj4+NTU1NHjRo1btw48+r00j38qamp0l8d+Do2pFWrVgkJCf369Rs7duyIESOaPklBvdavXy89YPw8AMBODKEHAMDX5ebmajQaIcR33303btw4d5cDAADqxyR2AAB4uU2bNk2ePHny5MmHDx+ut8M///lP6UHv3r1dWBcAAGgehtADAODl4uPjpUXXtFrtihUr6gwIP3369HvvvSeEuPHGG6Xr8AAAwDNxBR4AAC+XlpbWt29fIcQPP/xw991379y5s7S0tLKy8rfffnv77bfT0tIqKiqEEK+88oq7KwUAALZwDzwAAN7v4sWLt9xyS1ZWVkMdZs+ePXfuXFeWBAAAmosr8AAAeL/Y2NijR4++9957dQbJBwQEpKenr127lvQOAIDn4wo8AAC+RavV5ubmXrlyJSIiQqPRqNVqd1cEAACahAAPAAAAAIAMMIQeAAAAAAAZIMADAAAAACADBHgAAAAAAGSAAA8AAAAAgAwQ4AEAAAAAkAECPAAAAAAAMkCABwAAAABABgjwAAAAAADIAAEeAAAAAAAZIMADAAAAACADBHgAAAAAAGSAAA8AAAAAgAwQ4AEAAAAAkAECPAAAAAAAMkCABwAAAABABgjwAAAAAADIwP8D/hFwhaTQptQAAAAASUVORK5CYII=",alt:""})})]})}function Q(A={}){const{wrapper:e}={...(0,d.R)(),...A.components};return e?(0,n.jsx)(e,{...A,children:(0,n.jsx)(o,{...A})}):o(A)}},28453:(A,e,t)=>{t.d(e,{R:()=>v,x:()=>a});var r=t(96540);const n={},d=r.createContext(n);function v(A){const e=r.useContext(d);return r.useMemo((function(){return"function"==typeof A?A(e):{...e,...A}}),[e,A])}function a(A){let e;return e=A.disableParentContext?"function"==typeof A.components?A.components(n):A.components||n:v(A.components),r.createElement(d.Provider,{value:e},A.children)}}}]); \ No newline at end of file diff --git a/assets/js/13166252.13beca9d.js b/assets/js/13166252.464d7c47.js similarity index 99% rename from assets/js/13166252.13beca9d.js rename to assets/js/13166252.464d7c47.js index 39d84cf826..e89e0b69c6 100644 --- a/assets/js/13166252.13beca9d.js +++ b/assets/js/13166252.464d7c47.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6867],{63545:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"data_science/python","title":"Preparing to Analyze Your Data in Python","description":"If you\'d like to follow along with this tutorial but don\'t have a Python development environment set up, consider using Google Collab, a free service from Google Research.","source":"@site/docs/09-data_science/04-python.md","sourceDirName":"09-data_science","slug":"/data_science/python","permalink":"/data_science/python","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/04-python.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":4,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"How does the LAMP Data Format Work?","permalink":"/data_science/data"},"next":{"title":"Preparing to Analyze Your Data in R","permalink":"/data_science/r"}}');var i=n(74848),r=n(28453);const s={},o="Preparing to Analyze Your Data in Python",l={},c=[{value:"Protocol methods",id:"protocol-methods",level:2},{value:"Querying sensor data",id:"querying-sensor-data",level:3},{value:"Example: Query accelerometer data",id:"example-query-accelerometer-data",level:3},{value:"Query activity event data",id:"query-activity-event-data",level:3}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",strong:"strong",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"preparing-to-analyze-your-data-in-python",children:"Preparing to Analyze Your Data in Python"})}),"\n",(0,i.jsxs)(t.p,{children:["If you'd like to follow along with this tutorial but don't have a Python development environment set up, ",(0,i.jsxs)(t.strong,{children:["consider using ",(0,i.jsx)(t.a,{href:"https://colab.research.google.com/",children:"Google Collab"}),", a free service"]})," from Google Research."]}),"\n",(0,i.jsx)(t.h1,{id:"installation-and-setup",children:"Installation and Setup"}),"\n",(0,i.jsx)(t.p,{children:"First install the package."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"pip install LAMP-core\n"})}),"\n",(0,i.jsx)(t.p,{children:"Then, import the library and connect to the server."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"import LAMP\nLAMP.connect('my_email@address.com', 'my_password', 'api.lamp.digital')\n"})}),"\n",(0,i.jsx)(t.h1,{id:"usage",children:"Usage"}),"\n",(0,i.jsx)(t.h2,{id:"protocol-methods",children:"Protocol methods"}),"\n",(0,i.jsx)(t.p,{children:"Methods native to the LAMP API can now be called to pull data from the platform."}),"\n",(0,i.jsx)(t.p,{children:"For example, we can find all of the participants belonging to a Researcher:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"TEST_RESEARCHER = 'UmVzZWFyY2hlcjoxNjM~'\n\n[LAMP.Participant.all_by_study(study['id'])['data'] for study in LAMP.Study.all_by_researcher(TEST_RESEARCHER)['data']]\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"# OUTPUT\n\n#{'data': [{'id': 'U34260565',\n# 'language': 'en',\n# 'theme': '#359FFE',\n# 'emergency_contact': None,\n# 'helpline': None},\n# {'id': 'U33327158',\n# 'language': 'en',\n# 'theme': '#359FFE',\n# 'emergency_contact': None,\n# 'helpline': None}]}\n"})}),"\n",(0,i.jsx)(t.p,{children:"The code below will make CSV files of all the 'lamp.gps.contextual' sensor events for all participants under a given researcher id:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:"import LAMP\nimport pandas as pd \nLAMP.connect(\"MY_EMAIL_ADDRESS_HERE\", \"MY_PASSWORD_HERE\")\n\nfor participant in LAMP.Participant.all_by_researcher(\"me\")['data']:\n data = []\n events = LAMP.SensorEvent.all_by_participant(participant['id'], origin='lamp.gps.contextual')['data']\n for event in events:\n data.append({\n 'timestamp': event['timestamp'],\n 'UTC time': \"\",\n 'latitude': event['data']['latitude'],\n 'longitude': event['data']['longitude'],\n 'altitude': 1.0,\n 'accuracy': 1.0\n })\n # Don't make CSV files for participants without any `lamp.gps.contextual` events.\n if len(data) > 0:\n pd.DataFrame.from_dict(data, orient='columns').to_csv(f\"{participant['id']}.csv\", index=False)\n"})}),"\n",(0,i.jsx)(t.h3,{id:"querying-sensor-data",children:"Querying sensor data"}),"\n",(0,i.jsx)(t.p,{children:'Query sensor data with "all_by_participant"'}),"\n",(0,i.jsx)(t.p,{children:'Specify a sensor with "origin". If no origin is passed, it will try to query all sensors'}),"\n",(0,i.jsx)(t.p,{children:"Note that due to device or user specification, some spensors may not have data"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:'# Full sensor specs at https://docs.lamp.digital/Data-Types-99b045852c7b406f87c124b927fe95fa\n\n# Please note that no GPS data has been included with these dummy profiles\n\nparticipant_1 = "U5704591513"\nlamp_sensors = ["lamp.accelerometer", "lamp.accelerometer.motion", "lamp.analytics", \n "lamp.blood_pressure", "lamp.bluetooth", "lamp.calls", "lamp.distance",\n "lamp.flights", "lamp.gps", "lamp.gps.contextual", "lamp.gyroscope",\n "lamp.heart_rate", "lamp.height", "lamp.magnetometer", "lamp.respiratory_rate"\n "lamp.screen_state","lamp.segment", "lamp.sleep", "lamp.steps",\n "lamp.weight", "lamp.wifi"]\n\nLAMP.SensorEvent.all_by_participant(participant_1, origin="lamp.bluetooth")[\'data\'][:5]#, origin="lamp.calls")\n'})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:"[{'timestamp': 1578863459719,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==',\n 'RSSI': -71}},\n {'timestamp': 1578863459533,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==',\n 'RSSI': -74}},\n {'timestamp': 1578863459196,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==',\n 'RSSI': -60}},\n {'timestamp': 1578863459167,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': 'YyTeKHTPetzGdC0j2EPJ9-VJ9FxafDpHd34MA41BQDKSt1Q4B7vtuFJZpN7_JTOKnDycjRcA3ik8pYwcrfFGlQ==',\n 'RSSI': -98}},\n {'timestamp': 1578863458989,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': 'lYcGRvQlyI9Gq8Yqu1wDX8mOQJDBzIMnnGS9UsVxsrsmKWb1nFOY0tLLAE8VTzJ83GeJaBhmnhpL8weRv7A96Q==',\n 'RSSI': -97}}]\n"})}),"\n",(0,i.jsx)(t.h3,{id:"example-query-accelerometer-data",children:"Example: Query accelerometer data"}),"\n",(0,i.jsx)(t.p,{children:'Accelerometer data points are SensorEvents with the origin "lamp.accelerometer".'}),"\n",(0,i.jsxs)(t.p,{children:["See LAMP-py documentation at\xa0",(0,i.jsx)(t.a,{href:"https://github.com/BIDMCDigitalPsychiatry/LAMP-py",children:"https://github.com/BIDMCDigitalPsychiatry/LAMP-py"}),"\xa0for further API details."]}),"\n",(0,i.jsx)(t.p,{children:'Query responses are limtied to 1000 entries. In the event that there are more than 1000 events for a given sensor, the most recent 1000 events are returned. To access more data\u2014or to query during a specific time range\u2014you must use the "_to" and "from" parameters'}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:"# '_from' and 'to' are UNIX timestamps\nparticipant_accel_tr = LAMP.SensorEvent.all_by_participant(participant_1, \n origin=\"lamp.accelerometer\",\n _from=1577735460618,\n to=1577735460737)\nparticipant_accel_tr['data']\n"})}),"\n",(0,i.jsx)(t.h3,{id:"query-activity-event-data",children:"Query activity event data"}),"\n",(0,i.jsx)(t.p,{children:"Surveys are ActivityEvents, with each survey type defined as an Activity"}),"\n",(0,i.jsx)(t.p,{children:"'duration' is the survey completion time, in ms"}),"\n",(0,i.jsx)(t.p,{children:"'activity' is the Activity id"}),"\n",(0,i.jsx)(t.p,{children:"'temporal_slices' contains responses for each survey question"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"LAMP.ActivityEvent.all_by_participant(participant_1)['data'][0]\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"# {'timestamp': 1600557560000,\n# 'duration': 15000,\n# 'activity': '16fnz109gs4sehyfc84n',\n# 'static_data': {},\n# 'temporal_slices': [{'item': 'How did you feel this week?',\n# 'value': 'Okay',\n# 'type': 'valid',\n# 'duration': 5000,\n# 'level': None},\n# {'item': 'Have you been admitted to the hospital for psychiatric reasons in the past week?',\n# 'value': 'No',\n# 'type': 'valid',\n# 'duration': 7000,\n# 'level': None},\n# {'item': 'Use this space to write down your thoughts and feelings about the week. ',\n# 'value': 'it was okay',\n# 'type': 'valid',\n# 'duration': 3000,\n# 'level': None}]}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Details of the 'activity can be be viewed the following method"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"LAMP.Activity.view('16fnz109gs4sehyfc84n')\n"})})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>o});var a=n(96540);const i={},r=a.createContext(i);function s(e){const t=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6867],{63545:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"data_science/python","title":"Preparing to Analyze Your Data in Python","description":"If you\'d like to follow along with this tutorial but don\'t have a Python development environment set up, consider using Google Collab, a free service from Google Research.","source":"@site/docs/09-data_science/04-python.md","sourceDirName":"09-data_science","slug":"/data_science/python","permalink":"/data_science/python","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/04-python.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":4,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"How does the LAMP Data Format Work?","permalink":"/data_science/data"},"next":{"title":"Preparing to Analyze Your Data in R","permalink":"/data_science/r"}}');var i=n(74848),r=n(28453);const s={},o="Preparing to Analyze Your Data in Python",l={},c=[{value:"Protocol methods",id:"protocol-methods",level:2},{value:"Querying sensor data",id:"querying-sensor-data",level:3},{value:"Example: Query accelerometer data",id:"example-query-accelerometer-data",level:3},{value:"Query activity event data",id:"query-activity-event-data",level:3}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",strong:"strong",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"preparing-to-analyze-your-data-in-python",children:"Preparing to Analyze Your Data in Python"})}),"\n",(0,i.jsxs)(t.p,{children:["If you'd like to follow along with this tutorial but don't have a Python development environment set up, ",(0,i.jsxs)(t.strong,{children:["consider using ",(0,i.jsx)(t.a,{href:"https://colab.research.google.com/",children:"Google Collab"}),", a free service"]})," from Google Research."]}),"\n",(0,i.jsx)(t.h1,{id:"installation-and-setup",children:"Installation and Setup"}),"\n",(0,i.jsx)(t.p,{children:"First install the package."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"pip install LAMP-core\n"})}),"\n",(0,i.jsx)(t.p,{children:"Then, import the library and connect to the server."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"import LAMP\nLAMP.connect('my_email@address.com', 'my_password', 'api.lamp.digital')\n"})}),"\n",(0,i.jsx)(t.h1,{id:"usage",children:"Usage"}),"\n",(0,i.jsx)(t.h2,{id:"protocol-methods",children:"Protocol methods"}),"\n",(0,i.jsx)(t.p,{children:"Methods native to the LAMP API can now be called to pull data from the platform."}),"\n",(0,i.jsx)(t.p,{children:"For example, we can find all of the participants belonging to a Researcher:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"TEST_RESEARCHER = 'UmVzZWFyY2hlcjoxNjM~'\n\n[LAMP.Participant.all_by_study(study['id'])['data'] for study in LAMP.Study.all_by_researcher(TEST_RESEARCHER)['data']]\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"# OUTPUT\n\n#{'data': [{'id': 'U34260565',\n# 'language': 'en',\n# 'theme': '#359FFE',\n# 'emergency_contact': None,\n# 'helpline': None},\n# {'id': 'U33327158',\n# 'language': 'en',\n# 'theme': '#359FFE',\n# 'emergency_contact': None,\n# 'helpline': None}]}\n"})}),"\n",(0,i.jsx)(t.p,{children:"The code below will make CSV files of all the 'lamp.gps.contextual' sensor events for all participants under a given researcher id:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:"import LAMP\nimport pandas as pd \nLAMP.connect(\"MY_EMAIL_ADDRESS_HERE\", \"MY_PASSWORD_HERE\")\n\nfor participant in LAMP.Participant.all_by_researcher(\"me\")['data']:\n data = []\n events = LAMP.SensorEvent.all_by_participant(participant['id'], origin='lamp.gps.contextual')['data']\n for event in events:\n data.append({\n 'timestamp': event['timestamp'],\n 'UTC time': \"\",\n 'latitude': event['data']['latitude'],\n 'longitude': event['data']['longitude'],\n 'altitude': 1.0,\n 'accuracy': 1.0\n })\n # Don't make CSV files for participants without any `lamp.gps.contextual` events.\n if len(data) > 0:\n pd.DataFrame.from_dict(data, orient='columns').to_csv(f\"{participant['id']}.csv\", index=False)\n"})}),"\n",(0,i.jsx)(t.h3,{id:"querying-sensor-data",children:"Querying sensor data"}),"\n",(0,i.jsx)(t.p,{children:'Query sensor data with "all_by_participant"'}),"\n",(0,i.jsx)(t.p,{children:'Specify a sensor with "origin". If no origin is passed, it will try to query all sensors'}),"\n",(0,i.jsx)(t.p,{children:"Note that due to device or user specification, some spensors may not have data"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:'# Full sensor specs at https://docs.lamp.digital/Data-Types-99b045852c7b406f87c124b927fe95fa\n\n# Please note that no GPS data has been included with these dummy profiles\n\nparticipant_1 = "U5704591513"\nlamp_sensors = ["lamp.accelerometer", "lamp.accelerometer.motion", "lamp.analytics", \n "lamp.blood_pressure", "lamp.bluetooth", "lamp.calls", "lamp.distance",\n "lamp.flights", "lamp.gps", "lamp.gps.contextual", "lamp.gyroscope",\n "lamp.heart_rate", "lamp.height", "lamp.magnetometer", "lamp.respiratory_rate"\n "lamp.screen_state","lamp.segment", "lamp.sleep", "lamp.steps",\n "lamp.weight", "lamp.wifi"]\n\nLAMP.SensorEvent.all_by_participant(participant_1, origin="lamp.bluetooth")[\'data\'][:5]#, origin="lamp.calls")\n'})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:"[{'timestamp': 1578863459719,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==',\n 'RSSI': -71}},\n {'timestamp': 1578863459533,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==',\n 'RSSI': -74}},\n {'timestamp': 1578863459196,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==',\n 'RSSI': -60}},\n {'timestamp': 1578863459167,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': 'YyTeKHTPetzGdC0j2EPJ9-VJ9FxafDpHd34MA41BQDKSt1Q4B7vtuFJZpN7_JTOKnDycjRcA3ik8pYwcrfFGlQ==',\n 'RSSI': -98}},\n {'timestamp': 1578863458989,\n 'sensor': 'lamp.bluetooth',\n 'data': {'hashed MAC': 'lYcGRvQlyI9Gq8Yqu1wDX8mOQJDBzIMnnGS9UsVxsrsmKWb1nFOY0tLLAE8VTzJ83GeJaBhmnhpL8weRv7A96Q==',\n 'RSSI': -97}}]\n"})}),"\n",(0,i.jsx)(t.h3,{id:"example-query-accelerometer-data",children:"Example: Query accelerometer data"}),"\n",(0,i.jsx)(t.p,{children:'Accelerometer data points are SensorEvents with the origin "lamp.accelerometer".'}),"\n",(0,i.jsxs)(t.p,{children:["See LAMP-py documentation at\xa0",(0,i.jsx)(t.a,{href:"https://github.com/BIDMCDigitalPsychiatry/LAMP-py",children:"https://github.com/BIDMCDigitalPsychiatry/LAMP-py"}),"\xa0for further API details."]}),"\n",(0,i.jsx)(t.p,{children:'Query responses are limtied to 1000 entries. In the event that there are more than 1000 events for a given sensor, the most recent 1000 events are returned. To access more data\u2014or to query during a specific time range\u2014you must use the "_to" and "from" parameters'}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-jsx",children:"# '_from' and 'to' are UNIX timestamps\nparticipant_accel_tr = LAMP.SensorEvent.all_by_participant(participant_1, \n origin=\"lamp.accelerometer\",\n _from=1577735460618,\n to=1577735460737)\nparticipant_accel_tr['data']\n"})}),"\n",(0,i.jsx)(t.h3,{id:"query-activity-event-data",children:"Query activity event data"}),"\n",(0,i.jsx)(t.p,{children:"Surveys are ActivityEvents, with each survey type defined as an Activity"}),"\n",(0,i.jsx)(t.p,{children:"'duration' is the survey completion time, in ms"}),"\n",(0,i.jsx)(t.p,{children:"'activity' is the Activity id"}),"\n",(0,i.jsx)(t.p,{children:"'temporal_slices' contains responses for each survey question"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"LAMP.ActivityEvent.all_by_participant(participant_1)['data'][0]\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"# {'timestamp': 1600557560000,\n# 'duration': 15000,\n# 'activity': '16fnz109gs4sehyfc84n',\n# 'static_data': {},\n# 'temporal_slices': [{'item': 'How did you feel this week?',\n# 'value': 'Okay',\n# 'type': 'valid',\n# 'duration': 5000,\n# 'level': None},\n# {'item': 'Have you been admitted to the hospital for psychiatric reasons in the past week?',\n# 'value': 'No',\n# 'type': 'valid',\n# 'duration': 7000,\n# 'level': None},\n# {'item': 'Use this space to write down your thoughts and feelings about the week. ',\n# 'value': 'it was okay',\n# 'type': 'valid',\n# 'duration': 3000,\n# 'level': None}]}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Details of the 'activity can be be viewed the following method"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"LAMP.Activity.view('16fnz109gs4sehyfc84n')\n"})})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>o});var a=n(96540);const i={},r=a.createContext(i);function s(e){const t=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1397d9de.e8c2b32f.js b/assets/js/1397d9de.1eef78e5.js similarity index 99% rename from assets/js/1397d9de.e8c2b32f.js rename to assets/js/1397d9de.1eef78e5.js index 7a2882475a..2848301f47 100644 --- a/assets/js/1397d9de.e8c2b32f.js +++ b/assets/js/1397d9de.1eef78e5.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4527],{24890:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>g,frontMatter:()=>d,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"start_here/activities/create_tips","title":"Create and Customize Tips","description":"How to Create a Tip from the Patient Profile","source":"@site/docs/06-start_here/06-activities/01-create_tips.md","sourceDirName":"06-start_here/06-activities","slug":"/start_here/activities/create_tips","permalink":"/start_here/activities/create_tips","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/06-activities/01-create_tips.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":1,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Users vs Activities vs Sensors vs Studies Tab","permalink":"/start_here/users_vs_activities"},"next":{"title":"Create and Customize Surveys","permalink":"/start_here/activities/create_surveys"}}');var a=t(74848),s=t(28453);const d={},l="Create and Customize Tips",r={},c=[{value:"Basic Formatting",id:"basic-formatting",level:3},{value:"Advanced Formatting",id:"advanced-formatting",level:3},{value:"Embedding Media",id:"embedding-media",level:3}];function o(e){const n={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"create-and-customize-tips",children:"Create and Customize Tips"})}),"\n",(0,a.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/5Hf3CPCgC50",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.em,{children:"How to Create a Tip from the Patient Profile"})}),"\n",(0,a.jsx)(n.p,{children:"Navigate to the activities page click the \u201c+ Add\u201d button, and then scroll to the bottom and click \u201ctips\u201d."}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsxs)(n.li,{children:["Click the ",(0,a.jsx)(n.code,{children:"[+ Add]"})," button at the top right of the list to begin."]}),"\n",(0,a.jsx)(n.li,{children:"Select the study you wish to add the tip to."}),"\n",(0,a.jsx)(n.li,{children:"Title your tip."}),"\n",(0,a.jsx)(n.li,{children:"Copy and paste the link to the tip you want to add. If there is no link this will be left blank."}),"\n",(0,a.jsx)(n.li,{children:"Add the tip author. If there is no author, this will be left blank."}),"\n",(0,a.jsxs)(n.li,{children:["Press the ",(0,a.jsx)(n.code,{children:"(+)"})," icon to add an image."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(84175).A+"",width:"680",height:"1058"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(49560).A+"",width:"1758",height:"1088"})}),"\n",(0,a.jsx)(n.h1,{id:"customizing-the-content-of-your-tip",children:"Customizing the Content of Your Tip"}),"\n",(0,a.jsxs)(n.p,{children:["Tips support ",(0,a.jsx)(n.a,{href:"https://www.markdownguide.org/getting-started/",children:"Markdown-formatted text"}),", including basic HTML and embedded content such as YouTube videos or PDF documents. Markdown formatting is different than typical Word processing or other text editors, and uses special syntax to change how certain text is displayed. Examples of what you can do are provided below, but if you need more help, please see the Markdown Guide linked above."]}),"\n",(0,a.jsx)(n.h3,{id:"basic-formatting",children:"Basic Formatting"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(90895).A+"",width:"776",height:"906"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"# h1 Heading\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n###### h6 Heading\n\n---\n\n## Text\n\n**This is bold text**\n\n*This is italic text*\n\nEmojis in this text will be replaced like in Slack or GitHub: :dog: :+1:\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(77722).A+"",width:"776",height:"1168"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"## Lists\n\nUnordered\n\n+ Create a list by starting a line with `+`, `-`, or `*`\n+ Sub-lists are made by indenting 2 spaces:\n - Marker character change forces new list start:\n * Ac tristique libero volutpat at\n + Facilisis in pretium nisl aliquet\n - Nulla volutpat aliquam velit\n+ Very easy!\n\nOrdered\n\n1. Lorem ipsum dolor sit amet\n2. Consectetur adipiscing elit\n3. Integer molestie lorem at massa\n\n1. You can use sequential numbers...\n1. ...or keep all the numbers as `1.`\n\nStart numbering with offset:\n\n57. foo\n1. bar\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(95763).A+"",width:"776",height:"354"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(78497).A+"",width:"776",height:"656"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"## Blocks\n\nInline `block`\n\nParagraph blocks\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"Sample text here..."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"\n---\n\n## Quotes\n\n> Quotes can also be nested...\n>> ...by using additional greater-than signs right next to each other...\n> > > ...or with spaces between arrows.\n\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(48556).A+"",width:"776",height:"1144"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:'## Links & Media\n\n[link text](https://docs.lamp.digital)\n\n[link with title](https://docs.lamp.digital "Hello LAMP!")\n\n![flaticon](https://www.flaticon.com/svg/static/icons/svg/3823/3823851.svg)\n'})}),"\n",(0,a.jsx)(n.h3,{id:"advanced-formatting",children:"Advanced Formatting"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(85428).A+"",width:"776",height:"388"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"## Tables\n\n| hello | world | this | is | a |\n|:-:|-|-|-|-|\n| table | 1 | 2 | 3 | 4 |\n| abc | 123 | | | |\n| ![embedded image](https://www.flaticon.com/svg/static/icons/svg/3823/3823851.svg) | | 1. hi
2. hello | | **test** |\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(68221).A+"",width:"776",height:"1542"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:'
\nReady to watch a video?\n\n
\n\n
\nReady to read a book?\n\n
\n'})}),"\n",(0,a.jsx)(n.h3,{id:"embedding-media",children:"Embedding Media"}),"\n",(0,a.jsxs)(n.p,{children:["In some cases, if you're embedding media such as images or small PDF files, it's important to encode that data into the Markdown text itself, instead of using URLs. \u2192 ",(0,a.jsx)(n.a,{href:"https://dopiaza.org/tools/datauri/index.php",children:"You may need to use an online base64 converter tool, like this one."})," Upload the file, copy the text that appears and paste that as the \u201csrc=\u2026\u201d item."]}),"\n",(0,a.jsx)(n.p,{children:"Before (URL):"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"http://www.africau.edu/images/default/sample.pdf\n"})}),"\n",(0,a.jsx)(n.p,{children:"After (Embedded Data):"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"data:image/png;base64,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\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Full Markdown Sample"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"# h1 Heading\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n###### h6 Heading\n\n---\n\n## Text\n\n**This is bold text**\n\n*This is italic text*\n\nEmojis in this text will be replaced like in Slack or GitHub: :dog: :+1:\n\n---\n\n## Quotes\n\n> Quotes can also be nested...\n>> ...by using additional greater-than signs right next to each other...\n> > > ...or with spaces between arrows.\n\n---\n\n## Lists\n\nUnordered\n\n+ Create a list by starting a line with `+`, `-`, or `*`\n+ Sub-lists are made by indenting 2 spaces:\n - Marker character change forces new list start:\n * Ac tristique libero volutpat at\n + Facilisis in pretium nisl aliquet\n - Nulla volutpat aliquam velit\n+ Very easy!\n\nOrdered\n\n1. Lorem ipsum dolor sit amet\n2. Consectetur adipiscing elit\n3. Integer molestie lorem at massa\n\n1. You can use sequential numbers...\n1. ...or keep all the numbers as `1.`\n\nStart numbering with offset:\n\n57. foo\n1. bar\n\n---\n\n## Blocks\n\nInline `block`\n\nParagraph blocks\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"Sample text here..."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'\n---\n\n## Links & Media\n\n[link text](http://dev.nodeca.com)\n\n[link with title](http://nodeca.github.io/pica/demo/ "title text!")\n\n![image](https://www.flaticon.com/svg/static/icons/svg/3823/3823851.svg)\n\n
\nReady to watch a video?\n\n
\n\n
\nReady to read a book?\n\n
\n\n## Tables\n\n| hello | world | this | is | a |\n|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|-------|----------------|----|----------|\n| table | 1 | 2 | 3 | 4 |\n| abc | 123 | | | |\n| ![embedded image](data:image/png;base64,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) | | 1. hi 2. hello | | **test** |\n'})}),"\n"]}),"\n"]})]})}function g(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(o,{...e})}):o(e)}},90895:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.00.39_PM-b55ccde8b4ecdf0ad4d14766612a89ba.png"},77722:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.00.54_PM-f211d331ed951dd98beff603c8c1d610.png"},78497:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.12_PM-5189f2ae46a1b1c7c1ecf398d122b92c.png"},95763:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.29_PM-0dbb87ec4ef615540c090aba048a2491.png"},85428:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.46_PM-8bd7b38b31ad58ea4f80e9e0267ca4db.png"},48556:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.59_PM-55dfcc6ca4c82b19533e6fe2c2ea0eba.png"},68221:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.02.22_PM-7b6e7aa18b1de530a77716d3da2a9bee.png"},84175:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},49560:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/new_tip-0ab0e9e1db123c75ec907501edafa898.jpg"},28453:(e,n,t)=>{t.d(n,{R:()=>d,x:()=>l});var i=t(96540);const a={},s=i.createContext(a);function d(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:d(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4527],{24890:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>g,frontMatter:()=>d,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"start_here/activities/create_tips","title":"Create and Customize Tips","description":"How to Create a Tip from the Patient Profile","source":"@site/docs/06-start_here/06-activities/01-create_tips.md","sourceDirName":"06-start_here/06-activities","slug":"/start_here/activities/create_tips","permalink":"/start_here/activities/create_tips","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/06-activities/01-create_tips.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":1,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Users vs Activities vs Sensors vs Studies Tab","permalink":"/start_here/users_vs_activities"},"next":{"title":"Create and Customize Surveys","permalink":"/start_here/activities/create_surveys"}}');var a=t(74848),s=t(28453);const d={},l="Create and Customize Tips",r={},c=[{value:"Basic Formatting",id:"basic-formatting",level:3},{value:"Advanced Formatting",id:"advanced-formatting",level:3},{value:"Embedding Media",id:"embedding-media",level:3}];function o(e){const n={a:"a",code:"code",em:"em",h1:"h1",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"create-and-customize-tips",children:"Create and Customize Tips"})}),"\n",(0,a.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/5Hf3CPCgC50",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.em,{children:"How to Create a Tip from the Patient Profile"})}),"\n",(0,a.jsx)(n.p,{children:"Navigate to the activities page click the \u201c+ Add\u201d button, and then scroll to the bottom and click \u201ctips\u201d."}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsxs)(n.li,{children:["Click the ",(0,a.jsx)(n.code,{children:"[+ Add]"})," button at the top right of the list to begin."]}),"\n",(0,a.jsx)(n.li,{children:"Select the study you wish to add the tip to."}),"\n",(0,a.jsx)(n.li,{children:"Title your tip."}),"\n",(0,a.jsx)(n.li,{children:"Copy and paste the link to the tip you want to add. If there is no link this will be left blank."}),"\n",(0,a.jsx)(n.li,{children:"Add the tip author. If there is no author, this will be left blank."}),"\n",(0,a.jsxs)(n.li,{children:["Press the ",(0,a.jsx)(n.code,{children:"(+)"})," icon to add an image."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(84175).A+"",width:"680",height:"1058"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(49560).A+"",width:"1758",height:"1088"})}),"\n",(0,a.jsx)(n.h1,{id:"customizing-the-content-of-your-tip",children:"Customizing the Content of Your Tip"}),"\n",(0,a.jsxs)(n.p,{children:["Tips support ",(0,a.jsx)(n.a,{href:"https://www.markdownguide.org/getting-started/",children:"Markdown-formatted text"}),", including basic HTML and embedded content such as YouTube videos or PDF documents. Markdown formatting is different than typical Word processing or other text editors, and uses special syntax to change how certain text is displayed. Examples of what you can do are provided below, but if you need more help, please see the Markdown Guide linked above."]}),"\n",(0,a.jsx)(n.h3,{id:"basic-formatting",children:"Basic Formatting"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(90895).A+"",width:"776",height:"906"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"# h1 Heading\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n###### h6 Heading\n\n---\n\n## Text\n\n**This is bold text**\n\n*This is italic text*\n\nEmojis in this text will be replaced like in Slack or GitHub: :dog: :+1:\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(77722).A+"",width:"776",height:"1168"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"## Lists\n\nUnordered\n\n+ Create a list by starting a line with `+`, `-`, or `*`\n+ Sub-lists are made by indenting 2 spaces:\n - Marker character change forces new list start:\n * Ac tristique libero volutpat at\n + Facilisis in pretium nisl aliquet\n - Nulla volutpat aliquam velit\n+ Very easy!\n\nOrdered\n\n1. Lorem ipsum dolor sit amet\n2. Consectetur adipiscing elit\n3. Integer molestie lorem at massa\n\n1. You can use sequential numbers...\n1. ...or keep all the numbers as `1.`\n\nStart numbering with offset:\n\n57. foo\n1. bar\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(95763).A+"",width:"776",height:"354"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(78497).A+"",width:"776",height:"656"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"## Blocks\n\nInline `block`\n\nParagraph blocks\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"Sample text here..."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"\n---\n\n## Quotes\n\n> Quotes can also be nested...\n>> ...by using additional greater-than signs right next to each other...\n> > > ...or with spaces between arrows.\n\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(48556).A+"",width:"776",height:"1144"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:'## Links & Media\n\n[link text](https://docs.lamp.digital)\n\n[link with title](https://docs.lamp.digital "Hello LAMP!")\n\n![flaticon](https://www.flaticon.com/svg/static/icons/svg/3823/3823851.svg)\n'})}),"\n",(0,a.jsx)(n.h3,{id:"advanced-formatting",children:"Advanced Formatting"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(85428).A+"",width:"776",height:"388"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"## Tables\n\n| hello | world | this | is | a |\n|:-:|-|-|-|-|\n| table | 1 | 2 | 3 | 4 |\n| abc | 123 | | | |\n| ![embedded image](https://www.flaticon.com/svg/static/icons/svg/3823/3823851.svg) | | 1. hi
2. hello | | **test** |\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{src:t(68221).A+"",width:"776",height:"1542"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:'
\nReady to watch a video?\n\n
\n\n
\nReady to read a book?\n\n
\n'})}),"\n",(0,a.jsx)(n.h3,{id:"embedding-media",children:"Embedding Media"}),"\n",(0,a.jsxs)(n.p,{children:["In some cases, if you're embedding media such as images or small PDF files, it's important to encode that data into the Markdown text itself, instead of using URLs. \u2192 ",(0,a.jsx)(n.a,{href:"https://dopiaza.org/tools/datauri/index.php",children:"You may need to use an online base64 converter tool, like this one."})," Upload the file, copy the text that appears and paste that as the \u201csrc=\u2026\u201d item."]}),"\n",(0,a.jsx)(n.p,{children:"Before (URL):"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"http://www.africau.edu/images/default/sample.pdf\n"})}),"\n",(0,a.jsx)(n.p,{children:"After (Embedded Data):"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"data:image/png;base64,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\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Full Markdown Sample"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-markdown",children:"# h1 Heading\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n###### h6 Heading\n\n---\n\n## Text\n\n**This is bold text**\n\n*This is italic text*\n\nEmojis in this text will be replaced like in Slack or GitHub: :dog: :+1:\n\n---\n\n## Quotes\n\n> Quotes can also be nested...\n>> ...by using additional greater-than signs right next to each other...\n> > > ...or with spaces between arrows.\n\n---\n\n## Lists\n\nUnordered\n\n+ Create a list by starting a line with `+`, `-`, or `*`\n+ Sub-lists are made by indenting 2 spaces:\n - Marker character change forces new list start:\n * Ac tristique libero volutpat at\n + Facilisis in pretium nisl aliquet\n - Nulla volutpat aliquam velit\n+ Very easy!\n\nOrdered\n\n1. Lorem ipsum dolor sit amet\n2. Consectetur adipiscing elit\n3. Integer molestie lorem at massa\n\n1. You can use sequential numbers...\n1. ...or keep all the numbers as `1.`\n\nStart numbering with offset:\n\n57. foo\n1. bar\n\n---\n\n## Blocks\n\nInline `block`\n\nParagraph blocks\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"Sample text here..."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'\n---\n\n## Links & Media\n\n[link text](http://dev.nodeca.com)\n\n[link with title](http://nodeca.github.io/pica/demo/ "title text!")\n\n![image](https://www.flaticon.com/svg/static/icons/svg/3823/3823851.svg)\n\n
\nReady to watch a video?\n\n
\n\n
\nReady to read a book?\n\n
\n\n## Tables\n\n| hello | world | this | is | a |\n|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|-------|----------------|----|----------|\n| table | 1 | 2 | 3 | 4 |\n| abc | 123 | | | |\n| ![embedded image](data:image/png;base64,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) | | 1. hi 2. hello | | **test** |\n'})}),"\n"]}),"\n"]})]})}function g(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(o,{...e})}):o(e)}},90895:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.00.39_PM-b55ccde8b4ecdf0ad4d14766612a89ba.png"},77722:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.00.54_PM-f211d331ed951dd98beff603c8c1d610.png"},78497:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.12_PM-5189f2ae46a1b1c7c1ecf398d122b92c.png"},95763:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.29_PM-0dbb87ec4ef615540c090aba048a2491.png"},85428:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.46_PM-8bd7b38b31ad58ea4f80e9e0267ca4db.png"},48556:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.01.59_PM-55dfcc6ca4c82b19533e6fe2c2ea0eba.png"},68221:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/Screen_Shot_2020-12-01_at_2.02.22_PM-7b6e7aa18b1de530a77716d3da2a9bee.png"},84175:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},49560:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/new_tip-0ab0e9e1db123c75ec907501edafa898.jpg"},28453:(e,n,t)=>{t.d(n,{R:()=>d,x:()=>l});var i=t(96540);const a={},s=i.createContext(a);function d(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:d(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/14f41733.670f4577.js b/assets/js/14f41733.f0922384.js similarity index 98% rename from assets/js/14f41733.670f4577.js rename to assets/js/14f41733.f0922384.js index cd07d35040..c9dd7ff6c7 100644 --- a/assets/js/14f41733.670f4577.js +++ b/assets/js/14f41733.f0922384.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[8720],{20236:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"consortium/admin/sched_delete-activity","title":"Schedule or Delete an Activity","description":"Scheduling an Activity","source":"@site/docs/10-consortium/01-admin/12-sched_delete-activity.md","sourceDirName":"10-consortium/01-admin","slug":"/consortium/admin/sched_delete-activity","permalink":"/consortium/admin/sched_delete-activity","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/01-admin/12-sched_delete-activity.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":12,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create a Manage Activity","permalink":"/consortium/admin/create_manage_activity"},"next":{"title":"Create and Rename User","permalink":"/consortium/admin/create_user"}}');var a=i(74848),c=i(28453);const r={},s="Schedule or Delete an Activity",l={},d=[{value:"Scheduling an Activity",id:"scheduling-an-activity",level:2},{value:"Delete an Activity",id:"delete-an-activity",level:2}];function o(e){const t={em:"em",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,c.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"schedule-or-delete-an-activity",children:"Schedule or Delete an Activity"})}),"\n",(0,a.jsx)(t.h2,{id:"scheduling-an-activity",children:"Scheduling an Activity"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Log into the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsx)(t.li,{children:"Select the activity you would like to schedule by checking the box next to it's name."}),"\n",(0,a.jsx)(t.li,{children:"Click the arrow to the right of the Name."}),"\n",(0,a.jsx)(t.li,{children:"Click the plus sign to the far right to add a schedule."}),"\n",(0,a.jsx)(t.li,{children:"Select you Start Date, Time, Repeat Interval, etc."}),"\n",(0,a.jsx)(t.li,{children:"Click the check mark."}),"\n",(0,a.jsx)(t.li,{children:"The patient or participant will receive a feed item and a notification on their phone at the specified time."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(67833).A+"",width:"1744",height:"920"})}),"\n",(0,a.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/LegFC4ZB1ro",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:"How to schedule an activity from the Patient Profile"})}),"\n",(0,a.jsx)(t.h2,{id:"delete-an-activity",children:"Delete an Activity"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:"Log into the dashboard and navigate to the Activities tab."}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:"Select one or more activity you would like to delete."}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:"Press Delete/the trash can icon at the top of the list."}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.strong,{children:"All data saved under that survey activity is deleted for every patient in your clinic."}),"\nOnce deleted, a survey activity and any deleted data cannot be recovered."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(13999).A+"",width:"2440",height:"932"})})]})}function h(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(o,{...e})}):o(e)}},13999:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/delete_activities-8ab8e2045685dc3eefe88a4eee7cc90b.jpg"},67833:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/schedule-3b79ac50f4c51a0017bb81f1c062148b.jpg"},28453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>s});var n=i(96540);const a={},c=n.createContext(a);function r(e){const t=n.useContext(c);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),n.createElement(c.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[8720],{20236:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"consortium/admin/sched_delete-activity","title":"Schedule or Delete an Activity","description":"Scheduling an Activity","source":"@site/docs/10-consortium/01-admin/12-sched_delete-activity.md","sourceDirName":"10-consortium/01-admin","slug":"/consortium/admin/sched_delete-activity","permalink":"/consortium/admin/sched_delete-activity","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/01-admin/12-sched_delete-activity.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":12,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create a Manage Activity","permalink":"/consortium/admin/create_manage_activity"},"next":{"title":"Create and Rename User","permalink":"/consortium/admin/create_user"}}');var a=i(74848),c=i(28453);const r={},s="Schedule or Delete an Activity",l={},d=[{value:"Scheduling an Activity",id:"scheduling-an-activity",level:2},{value:"Delete an Activity",id:"delete-an-activity",level:2}];function o(e){const t={em:"em",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,c.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"schedule-or-delete-an-activity",children:"Schedule or Delete an Activity"})}),"\n",(0,a.jsx)(t.h2,{id:"scheduling-an-activity",children:"Scheduling an Activity"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Log into the dashboard and navigate to the Activities tab."}),"\n",(0,a.jsx)(t.li,{children:"Select the activity you would like to schedule by checking the box next to it's name."}),"\n",(0,a.jsx)(t.li,{children:"Click the arrow to the right of the Name."}),"\n",(0,a.jsx)(t.li,{children:"Click the plus sign to the far right to add a schedule."}),"\n",(0,a.jsx)(t.li,{children:"Select you Start Date, Time, Repeat Interval, etc."}),"\n",(0,a.jsx)(t.li,{children:"Click the check mark."}),"\n",(0,a.jsx)(t.li,{children:"The patient or participant will receive a feed item and a notification on their phone at the specified time."}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(67833).A+"",width:"1744",height:"920"})}),"\n",(0,a.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/LegFC4ZB1ro",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.em,{children:"How to schedule an activity from the Patient Profile"})}),"\n",(0,a.jsx)(t.h2,{id:"delete-an-activity",children:"Delete an Activity"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:"Log into the dashboard and navigate to the Activities tab."}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:"Select one or more activity you would like to delete."}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:"Press Delete/the trash can icon at the top of the list."}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.strong,{children:"All data saved under that survey activity is deleted for every patient in your clinic."}),"\nOnce deleted, a survey activity and any deleted data cannot be recovered."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{src:i(13999).A+"",width:"2440",height:"932"})})]})}function h(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(o,{...e})}):o(e)}},13999:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/delete_activities-8ab8e2045685dc3eefe88a4eee7cc90b.jpg"},67833:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/schedule-3b79ac50f4c51a0017bb81f1c062148b.jpg"},28453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>s});var n=i(96540);const a={},c=n.createContext(a);function r(e){const t=n.useContext(c);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),n.createElement(c.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/168fe559.f7d7261b.js b/assets/js/168fe559.e86a4553.js similarity index 98% rename from assets/js/168fe559.f7d7261b.js rename to assets/js/168fe559.e86a4553.js index 9cef5965b5..d511afa607 100644 --- a/assets/js/168fe559.f7d7261b.js +++ b/assets/js/168fe559.e86a4553.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6052],{35756:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"develop/cron_jobs","title":"Scheduling Tasks with Cron Jobs in LAMP","description":"While using LAMP, you may wish to schedule events or scripts to run on a regular basis - for example, analysis scripts or scripts that schedule study participants for different studies based on different criteria.","source":"@site/docs/08-develop/08-cron_jobs.md","sourceDirName":"08-develop","slug":"/develop/cron_jobs","permalink":"/develop/cron_jobs","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/08-develop/08-cron_jobs.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":8,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"App Gateway","permalink":"/develop/app_gateway"},"next":{"title":"Creating a Github Release","permalink":"/develop/Repositories/creating-github-release"}}');var t=n(74848),o=n(28453);const i={},a="Scheduling Tasks with Cron Jobs in LAMP",c={},l=[{value:"1. Create a manager service",id:"1-create-a-manager-service",level:4},{value:"2. Create the script service.",id:"2-create-the-script-service",level:4}];function d(e){const r={a:"a",code:"code",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.header,{children:(0,t.jsx)(r.h1,{id:"scheduling-tasks-with-cron-jobs-in-lamp",children:"Scheduling Tasks with Cron Jobs in LAMP"})}),"\n",(0,t.jsx)(r.p,{children:"While using LAMP, you may wish to schedule events or scripts to run on a regular basis - for example, analysis scripts or scripts that schedule study participants for different studies based on different criteria."}),"\n",(0,t.jsxs)(r.p,{children:["If you are using Portainer to support LAMP, you can use the following method and the ",(0,t.jsx)(r.a,{href:"https://github.com/crazy-max/swarm-cronjob",children:"swarm-cronjob"})," project to schedule these scripts to run regularly."]}),"\n",(0,t.jsx)(r.h4,{id:"1-create-a-manager-service",children:"1. Create a manager service"}),"\n",(0,t.jsx)(r.p,{children:"To create a manager service, add the following service to a stack (if you do not have a dedicated cron stack, you may wish to create one).It should look something like this:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{children:' manager:\n image: crazymax/swarm-cronjob\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock:ro\n environment:\n TZ: "America/New_York"\n'})}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsxs)(r.li,{children:["Image should be ",(0,t.jsx)(r.code,{children:"crazymax/swarm-cronjob"})]}),"\n",(0,t.jsxs)(r.li,{children:["Volume should be ",(0,t.jsx)(r.code,{children:"/var/run/docker.sock:/var/run/docker.sock:ro"})]}),"\n",(0,t.jsx)(r.li,{children:"The TZ env variable should be set to your local timezone - this will affect the times your scripts run if you specify an hour for them to run."}),"\n"]}),"\n",(0,t.jsxs)(r.p,{children:["Only do this step ",(0,t.jsx)(r.strong,{children:"ONCE"}),", regardless of how many services you plan to create."]}),"\n",(0,t.jsx)(r.h4,{id:"2-create-the-script-service",children:"2. Create the script service."}),"\n",(0,t.jsx)(r.p,{children:"Second, create the service that will run your script. It should look similar to this:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{children:' my_analysis:\n image: python:3.8\n command: [\'python\',\'/script/my_cool_script.py\']\n environment:\n TZ: "America/New_York"\n ANALYSIS_NAME: "My Analysis"\n volumes:\n - /usr/bin:/script\n - /var/run/docker.sock:/var/run/docker.sock:ro\n deploy:\n mode: replicated\n replicas: 0\n restart_policy:\n condition: none\n labels:\n swarm.cronjob.enable: "true"\n swarm.cronjob.schedule: "0 3 * * *"\n swarm.cronjob.skip-running: "false"\n'})}),"\n",(0,t.jsx)(r.p,{children:"N.B."}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"To install additional modules not included with the standard python3.8 image (for example), you may wish to run pip install commands through a shell script."}),"\n",(0,t.jsxs)(r.li,{children:["Use swarm.cronjob.schedule to enter your ",(0,t.jsx)(r.a,{href:"https://crontab.guru/",children:"cron string"})]}),"\n"]}),"\n",(0,t.jsx)(r.p,{children:"Do this step for each service you plan to create. After you update the stack, the script should begin running as scheduled. The service above, for instance, will run at daily at 3 AM."})]})}function h(e={}){const{wrapper:r}={...(0,o.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},28453:(e,r,n)=>{n.d(r,{R:()=>i,x:()=>a});var s=n(96540);const t={},o=s.createContext(t);function i(e){const r=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),s.createElement(o.Provider,{value:r},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6052],{35756:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"develop/cron_jobs","title":"Scheduling Tasks with Cron Jobs in LAMP","description":"While using LAMP, you may wish to schedule events or scripts to run on a regular basis - for example, analysis scripts or scripts that schedule study participants for different studies based on different criteria.","source":"@site/docs/08-develop/08-cron_jobs.md","sourceDirName":"08-develop","slug":"/develop/cron_jobs","permalink":"/develop/cron_jobs","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/08-develop/08-cron_jobs.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":8,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"App Gateway","permalink":"/develop/app_gateway"},"next":{"title":"Creating a Github Release","permalink":"/develop/Repositories/creating-github-release"}}');var t=n(74848),o=n(28453);const i={},a="Scheduling Tasks with Cron Jobs in LAMP",c={},l=[{value:"1. Create a manager service",id:"1-create-a-manager-service",level:4},{value:"2. Create the script service.",id:"2-create-the-script-service",level:4}];function d(e){const r={a:"a",code:"code",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.header,{children:(0,t.jsx)(r.h1,{id:"scheduling-tasks-with-cron-jobs-in-lamp",children:"Scheduling Tasks with Cron Jobs in LAMP"})}),"\n",(0,t.jsx)(r.p,{children:"While using LAMP, you may wish to schedule events or scripts to run on a regular basis - for example, analysis scripts or scripts that schedule study participants for different studies based on different criteria."}),"\n",(0,t.jsxs)(r.p,{children:["If you are using Portainer to support LAMP, you can use the following method and the ",(0,t.jsx)(r.a,{href:"https://github.com/crazy-max/swarm-cronjob",children:"swarm-cronjob"})," project to schedule these scripts to run regularly."]}),"\n",(0,t.jsx)(r.h4,{id:"1-create-a-manager-service",children:"1. Create a manager service"}),"\n",(0,t.jsx)(r.p,{children:"To create a manager service, add the following service to a stack (if you do not have a dedicated cron stack, you may wish to create one).It should look something like this:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{children:' manager:\n image: crazymax/swarm-cronjob\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock:ro\n environment:\n TZ: "America/New_York"\n'})}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsxs)(r.li,{children:["Image should be ",(0,t.jsx)(r.code,{children:"crazymax/swarm-cronjob"})]}),"\n",(0,t.jsxs)(r.li,{children:["Volume should be ",(0,t.jsx)(r.code,{children:"/var/run/docker.sock:/var/run/docker.sock:ro"})]}),"\n",(0,t.jsx)(r.li,{children:"The TZ env variable should be set to your local timezone - this will affect the times your scripts run if you specify an hour for them to run."}),"\n"]}),"\n",(0,t.jsxs)(r.p,{children:["Only do this step ",(0,t.jsx)(r.strong,{children:"ONCE"}),", regardless of how many services you plan to create."]}),"\n",(0,t.jsx)(r.h4,{id:"2-create-the-script-service",children:"2. Create the script service."}),"\n",(0,t.jsx)(r.p,{children:"Second, create the service that will run your script. It should look similar to this:"}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{children:' my_analysis:\n image: python:3.8\n command: [\'python\',\'/script/my_cool_script.py\']\n environment:\n TZ: "America/New_York"\n ANALYSIS_NAME: "My Analysis"\n volumes:\n - /usr/bin:/script\n - /var/run/docker.sock:/var/run/docker.sock:ro\n deploy:\n mode: replicated\n replicas: 0\n restart_policy:\n condition: none\n labels:\n swarm.cronjob.enable: "true"\n swarm.cronjob.schedule: "0 3 * * *"\n swarm.cronjob.skip-running: "false"\n'})}),"\n",(0,t.jsx)(r.p,{children:"N.B."}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsx)(r.li,{children:"To install additional modules not included with the standard python3.8 image (for example), you may wish to run pip install commands through a shell script."}),"\n",(0,t.jsxs)(r.li,{children:["Use swarm.cronjob.schedule to enter your ",(0,t.jsx)(r.a,{href:"https://crontab.guru/",children:"cron string"})]}),"\n"]}),"\n",(0,t.jsx)(r.p,{children:"Do this step for each service you plan to create. After you update the stack, the script should begin running as scheduled. The service above, for instance, will run at daily at 3 AM."})]})}function h(e={}){const{wrapper:r}={...(0,o.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},28453:(e,r,n)=>{n.d(r,{R:()=>i,x:()=>a});var s=n(96540);const t={},o=s.createContext(t);function i(e){const r=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),s.createElement(o.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/172c1bf5.1be01d9a.js b/assets/js/172c1bf5.8b159674.js similarity index 96% rename from assets/js/172c1bf5.1be01d9a.js rename to assets/js/172c1bf5.8b159674.js index 3aa25e1eb1..e7a36231c9 100644 --- a/assets/js/172c1bf5.1be01d9a.js +++ b/assets/js/172c1bf5.8b159674.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[3332],{12288:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>p});const i=JSON.parse('{"id":"consortium/patient/read_tip","title":"Read a Tip","description":"","source":"@site/docs/10-consortium/03-patient/04-read_tip.md","sourceDirName":"10-consortium/03-patient","slug":"/consortium/patient/read_tip","permalink":"/consortium/patient/read_tip","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/03-patient/04-read_tip.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":4,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Logging into LAMP","permalink":"/consortium/patient/login"},"next":{"title":"Take Surveys and Complete Activities","permalink":"/consortium/patient/complete_activities"}}');var a=n(74848),o=n(28453);const r={},s="Read a Tip",c={},p=[];function d(t){const e={h1:"h1",header:"header",...(0,o.R)(),...t.components};return(0,a.jsx)(e.header,{children:(0,a.jsx)(e.h1,{id:"read-a-tip",children:"Read a Tip"})})}function u(t={}){const{wrapper:e}={...(0,o.R)(),...t.components};return e?(0,a.jsx)(e,{...t,children:(0,a.jsx)(d,{...t})}):d(t)}},28453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>s});var i=n(96540);const a={},o=i.createContext(a);function r(t){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(a):t.components||a:r(t.components),i.createElement(o.Provider,{value:e},t.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[3332],{12288:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>p});const i=JSON.parse('{"id":"consortium/patient/read_tip","title":"Read a Tip","description":"","source":"@site/docs/10-consortium/03-patient/04-read_tip.md","sourceDirName":"10-consortium/03-patient","slug":"/consortium/patient/read_tip","permalink":"/consortium/patient/read_tip","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/03-patient/04-read_tip.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":4,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Logging into LAMP","permalink":"/consortium/patient/login"},"next":{"title":"Take Surveys and Complete Activities","permalink":"/consortium/patient/complete_activities"}}');var a=n(74848),o=n(28453);const r={},s="Read a Tip",c={},p=[];function d(t){const e={h1:"h1",header:"header",...(0,o.R)(),...t.components};return(0,a.jsx)(e.header,{children:(0,a.jsx)(e.h1,{id:"read-a-tip",children:"Read a Tip"})})}function u(t={}){const{wrapper:e}={...(0,o.R)(),...t.components};return e?(0,a.jsx)(e,{...t,children:(0,a.jsx)(d,{...t})}):d(t)}},28453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>s});var i=n(96540);const a={},o=i.createContext(a);function r(t){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(a):t.components||a:r(t.components),i.createElement(o.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/1880bda4.05c68e50.js b/assets/js/1880bda4.68de7617.js similarity index 99% rename from assets/js/1880bda4.05c68e50.js rename to assets/js/1880bda4.68de7617.js index f6783f4146..6c38064abf 100644 --- a/assets/js/1880bda4.05c68e50.js +++ b/assets/js/1880bda4.68de7617.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4821],{27536:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"start_here/logging_in","title":"Log In Information, Tips, and Tricks","description":"Logging In","source":"@site/docs/06-start_here/03-logging_in.md","sourceDirName":"06-start_here","slug":"/start_here/logging_in","permalink":"/start_here/logging_in","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/03-logging_in.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":3,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Accessing Your Account","permalink":"/start_here/accessing_account"},"next":{"title":"Create or Manage Patients and Participants","permalink":"/start_here/create_patients_participants"}}');var s=i(74848),a=i(28453);const r={},l="Log In Information, Tips, and Tricks",d={},c=[{value:"Logging In",id:"logging-in",level:2},{value:"Create a New Researcher or Clinician Credential (Admins Only)",id:"create-a-new-researcher-or-clinician-credential-admins-only",level:2},{value:"Video Tutorial",id:"video-tutorial",level:3},{value:"Reset a Clinican's or Researcher's Password (Admins Only)",id:"reset-a-clinicans-or-researchers-password-admins-only",level:2},{value:"Delete an Existing Clinician or Researcher Credential (Admins Only)",id:"delete-an-existing-clinician-or-researcher-credential-admins-only",level:2},{value:"Change a Clinician or Researcher Log In Email (Admins Only)",id:"change-a-clinician-or-researcher-log-in-email-admins-only",level:2},{value:"Sharing the QR Code and Log in Link for an Established Patient.",id:"sharing-the-qr-code-and-log-in-link-for-an-established-patient",level:2},{value:"Clinician vs Patient Credentials",id:"clinician-vs-patient-credentials",level:2}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"log-in-information-tips-and-tricks",children:"Log In Information, Tips, and Tricks"})}),"\n",(0,s.jsx)(n.h2,{id:"logging-in",children:"Logging In"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(57398).A+"",width:"664",height:"1162"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Open your preferred browser (Google Chrome, Firefox, Safari, Internet Explorer 11+ recommended)."}),"\n",(0,s.jsxs)(n.li,{children:["Navigate to ",(0,s.jsx)(n.a,{href:"https://dashboard.lamp.digital",children:"https://dashboard.lamp.digital"}),"."]}),"\n",(0,s.jsx)(n.li,{children:"Enter your username and password."}),"\n",(0,s.jsx)(n.li,{children:'Select "Login."'}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"create-a-new-researcher-or-clinician-credential-admins-only",children:"Create a New Researcher or Clinician Credential (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(11776).A+"",width:"864",height:"662"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top left in the blue bar and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["Tap the ",(0,s.jsx)(n.code,{children:"[+]"})," icon and enter only: ",(0,s.jsx)(n.strong,{children:"Name, Email Address, and Password."})," You can ignore the ",(0,s.jsx)(n.strong,{children:"Image"})," and ",(0,s.jsx)(n.strong,{children:"Role"})," field."]}),"\n",(0,s.jsx)(n.li,{children:"Click the check mark to save your credential."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Note that the email address you provide ",(0,s.jsx)(n.strong,{children:"MUST NOT"})," already be used across any credentials in your instance of the LAMP Platform. If the email address specified is already taken, your credential will fail to be created."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.strong,{children:"Name"})," field of your very first credential will always be reset to ",(0,s.jsx)(n.code,{children:"Default Credential"}),"."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(46647).A+"",width:"1280",height:"458"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(87625).A+"",width:"1280",height:"1606"})}),"\n",(0,s.jsx)(n.h3,{id:"video-tutorial",children:"Video Tutorial"}),"\n",(0,s.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/mp9HrcIt4B0",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,s.jsx)(n.h2,{id:"reset-a-clinicans-or-researchers-password-admins-only",children:"Reset a Clinican's or Researcher's Password (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(53634).A+"",width:"444",height:"546"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(80597).A+"",width:"1280",height:"458"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(77815).A+"",width:"1280",height:"722"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsx)(n.li,{children:"Tap the credential whose password you wish to change"}),"\n",(0,s.jsx)(n.li,{children:"Enter the password and tap the check mark icon at the right side of the text box to save your new password."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"DO NOT"})," attempt to reset the password of the credential you are currently using to log into and access mindLAMP. This may prevent you from using the app and lock you out."]}),"\n",(0,s.jsx)(n.h2,{id:"delete-an-existing-clinician-or-researcher-credential-admins-only",children:"Delete an Existing Clinician or Researcher Credential (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(53634).A+"",width:"444",height:"546"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["To delete a credential that already exists, tap its icon and select the ",(0,s.jsx)(n.code,{children:"Delete"})," option from the drop-down list."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Please note that this only deletes only the access to data, not the data itself; deleting an object and deleting a credential are different in the LAMP Platform. If no credentials remain, then there is no way to log in from the mindLAMP app."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(36569).A+"",width:"1434",height:"630"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(94180).A+"",width:"1280",height:"1378"})}),"\n",(0,s.jsx)(n.h2,{id:"change-a-clinician-or-researcher-log-in-email-admins-only",children:"Change a Clinician or Researcher Log In Email (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(53634).A+"",width:"444",height:"546"})}),"\n",(0,s.jsx)(n.p,{children:"To change a log in email for a clinician, you must create a new credential and delete the old one."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["Tap the ",(0,s.jsx)(n.code,{children:"[+]"})," icon and enter only: ",(0,s.jsx)(n.strong,{children:"Name, Email Address, and Password."})," You can ignore the ",(0,s.jsx)(n.strong,{children:"Image"})," and ",(0,s.jsx)(n.strong,{children:"Role"})," field."]}),"\n",(0,s.jsx)(n.li,{children:"Click the check mark to save your credential."}),"\n",(0,s.jsx)(n.li,{children:"Again, tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["To delete the old credential, tap its icon and select the ",(0,s.jsx)(n.code,{children:"Delete"})," option from the drop-down list."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(46647).A+"",width:"1280",height:"458"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(87625).A+"",width:"1280",height:"1606"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(36569).A+"",width:"1434",height:"630"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"If you are locked out of your account, please consult your clinician or system administrator/your organization's IT department for assistance."})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(36569).A+"",width:"1434",height:"630"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(94180).A+"",width:"1280",height:"1378"})}),"\n",(0,s.jsx)(n.h2,{id:"sharing-the-qr-code-and-log-in-link-for-an-established-patient",children:"Sharing the QR Code and Log in Link for an Established Patient."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Check the box next to the patient\u2019s name."}),"\n",(0,s.jsx)(n.li,{children:"Click on the \u201cEdit Password\u201d option."}),"\n",(0,s.jsx)(n.li,{children:"Change the password."}),"\n",(0,s.jsx)(n.li,{children:"Click on the floppy disk icon and the QR code will appear underneath the text field."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(30320).A+"",width:"2052",height:"850"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(99343).A+"",width:"1434",height:"1476"})}),"\n",(0,s.jsx)(n.h2,{id:"clinician-vs-patient-credentials",children:"Clinician vs Patient Credentials"}),"\n",(0,s.jsx)(n.p,{children:"Managing credentials for yourself or others is as follows:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"I am a clinician or researcher and want to manage my own credentials."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(11776).A+"",width:"864",height:"662"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["I am a clinician or researcher and want to ",(0,s.jsx)(n.strong,{children:"manage the credentials of a patient or participant."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Tap the Edit Password after checking the patient's name."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(15357).A+"",width:"1925",height:"425"})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(o,{...e})}):o(e)}},57398:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-09-21_at_10.56.36_AM-2b2881d3362d58450a36ff6f6f913a4d.png"},87625:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.26.07_PM-cfc0eb83c0588a3dc0edc8da83ccf0e1.png"},46647:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.27.24_PM-1bfc5391781f336964a42762894d5d08.png"},80597:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.27.40_PM-0c49e9e7bb2ef55bfa03ce28f945a06d.png"},77815:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.27.55_PM-e4682f9ff28853a5a1641e6928bda333.png"},94180:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.28.11_PM-85b6a9111458ad24709f69a74534c99c.png"},11776:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_55-78b704fa0795583fec9d0be4f7243b84.jpeg"},53634:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_61-e8c5bf00d985bae93edfbc966b34a22b.png"},36569:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_62-8d9d14dbf7ff96ba2a8128349b0ebc74.png"},30320:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_63-547c0d0a88be623a091649c0d519aaa9.png"},99343:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_64-c69c21ade0ef0e8641c2fd5d0b49f3ea.png"},15357:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_66-f98f18cda775bafe157eafa956429546.png"},16943:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/users_tab-0e262569eb9e13f7ab30e02d75433857.jpg"},28453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>l});var t=i(96540);const s={},a=t.createContext(s);function r(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4821],{27536:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"start_here/logging_in","title":"Log In Information, Tips, and Tricks","description":"Logging In","source":"@site/docs/06-start_here/03-logging_in.md","sourceDirName":"06-start_here","slug":"/start_here/logging_in","permalink":"/start_here/logging_in","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/03-logging_in.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":3,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Accessing Your Account","permalink":"/start_here/accessing_account"},"next":{"title":"Create or Manage Patients and Participants","permalink":"/start_here/create_patients_participants"}}');var s=i(74848),a=i(28453);const r={},l="Log In Information, Tips, and Tricks",d={},c=[{value:"Logging In",id:"logging-in",level:2},{value:"Create a New Researcher or Clinician Credential (Admins Only)",id:"create-a-new-researcher-or-clinician-credential-admins-only",level:2},{value:"Video Tutorial",id:"video-tutorial",level:3},{value:"Reset a Clinican's or Researcher's Password (Admins Only)",id:"reset-a-clinicans-or-researchers-password-admins-only",level:2},{value:"Delete an Existing Clinician or Researcher Credential (Admins Only)",id:"delete-an-existing-clinician-or-researcher-credential-admins-only",level:2},{value:"Change a Clinician or Researcher Log In Email (Admins Only)",id:"change-a-clinician-or-researcher-log-in-email-admins-only",level:2},{value:"Sharing the QR Code and Log in Link for an Established Patient.",id:"sharing-the-qr-code-and-log-in-link-for-an-established-patient",level:2},{value:"Clinician vs Patient Credentials",id:"clinician-vs-patient-credentials",level:2}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"log-in-information-tips-and-tricks",children:"Log In Information, Tips, and Tricks"})}),"\n",(0,s.jsx)(n.h2,{id:"logging-in",children:"Logging In"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(57398).A+"",width:"664",height:"1162"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Open your preferred browser (Google Chrome, Firefox, Safari, Internet Explorer 11+ recommended)."}),"\n",(0,s.jsxs)(n.li,{children:["Navigate to ",(0,s.jsx)(n.a,{href:"https://dashboard.lamp.digital",children:"https://dashboard.lamp.digital"}),"."]}),"\n",(0,s.jsx)(n.li,{children:"Enter your username and password."}),"\n",(0,s.jsx)(n.li,{children:'Select "Login."'}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"create-a-new-researcher-or-clinician-credential-admins-only",children:"Create a New Researcher or Clinician Credential (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(11776).A+"",width:"864",height:"662"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top left in the blue bar and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["Tap the ",(0,s.jsx)(n.code,{children:"[+]"})," icon and enter only: ",(0,s.jsx)(n.strong,{children:"Name, Email Address, and Password."})," You can ignore the ",(0,s.jsx)(n.strong,{children:"Image"})," and ",(0,s.jsx)(n.strong,{children:"Role"})," field."]}),"\n",(0,s.jsx)(n.li,{children:"Click the check mark to save your credential."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Note that the email address you provide ",(0,s.jsx)(n.strong,{children:"MUST NOT"})," already be used across any credentials in your instance of the LAMP Platform. If the email address specified is already taken, your credential will fail to be created."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.strong,{children:"Name"})," field of your very first credential will always be reset to ",(0,s.jsx)(n.code,{children:"Default Credential"}),"."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(46647).A+"",width:"1280",height:"458"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(87625).A+"",width:"1280",height:"1606"})}),"\n",(0,s.jsx)(n.h3,{id:"video-tutorial",children:"Video Tutorial"}),"\n",(0,s.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/mp9HrcIt4B0",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,s.jsx)(n.h2,{id:"reset-a-clinicans-or-researchers-password-admins-only",children:"Reset a Clinican's or Researcher's Password (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(53634).A+"",width:"444",height:"546"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(80597).A+"",width:"1280",height:"458"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(77815).A+"",width:"1280",height:"722"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsx)(n.li,{children:"Tap the credential whose password you wish to change"}),"\n",(0,s.jsx)(n.li,{children:"Enter the password and tap the check mark icon at the right side of the text box to save your new password."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"DO NOT"})," attempt to reset the password of the credential you are currently using to log into and access mindLAMP. This may prevent you from using the app and lock you out."]}),"\n",(0,s.jsx)(n.h2,{id:"delete-an-existing-clinician-or-researcher-credential-admins-only",children:"Delete an Existing Clinician or Researcher Credential (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(53634).A+"",width:"444",height:"546"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["To delete a credential that already exists, tap its icon and select the ",(0,s.jsx)(n.code,{children:"Delete"})," option from the drop-down list."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Please note that this only deletes only the access to data, not the data itself; deleting an object and deleting a credential are different in the LAMP Platform. If no credentials remain, then there is no way to log in from the mindLAMP app."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(36569).A+"",width:"1434",height:"630"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(94180).A+"",width:"1280",height:"1378"})}),"\n",(0,s.jsx)(n.h2,{id:"change-a-clinician-or-researcher-log-in-email-admins-only",children:"Change a Clinician or Researcher Log In Email (Admins Only)"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(53634).A+"",width:"444",height:"546"})}),"\n",(0,s.jsx)(n.p,{children:"To change a log in email for a clinician, you must create a new credential and delete the old one."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["Tap the ",(0,s.jsx)(n.code,{children:"[+]"})," icon and enter only: ",(0,s.jsx)(n.strong,{children:"Name, Email Address, and Password."})," You can ignore the ",(0,s.jsx)(n.strong,{children:"Image"})," and ",(0,s.jsx)(n.strong,{children:"Role"})," field."]}),"\n",(0,s.jsx)(n.li,{children:"Click the check mark to save your credential."}),"\n",(0,s.jsx)(n.li,{children:"Again, tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n",(0,s.jsxs)(n.li,{children:["To delete the old credential, tap its icon and select the ",(0,s.jsx)(n.code,{children:"Delete"})," option from the drop-down list."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(46647).A+"",width:"1280",height:"458"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(87625).A+"",width:"1280",height:"1606"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(36569).A+"",width:"1434",height:"630"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"If you are locked out of your account, please consult your clinician or system administrator/your organization's IT department for assistance."})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(36569).A+"",width:"1434",height:"630"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(94180).A+"",width:"1280",height:"1378"})}),"\n",(0,s.jsx)(n.h2,{id:"sharing-the-qr-code-and-log-in-link-for-an-established-patient",children:"Sharing the QR Code and Log in Link for an Established Patient."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(16943).A+"",width:"2358",height:"420"})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:'Log into the app and click on the "Users" tab.'}),"\n",(0,s.jsx)(n.li,{children:"Check the box next to the patient\u2019s name."}),"\n",(0,s.jsx)(n.li,{children:"Click on the \u201cEdit Password\u201d option."}),"\n",(0,s.jsx)(n.li,{children:"Change the password."}),"\n",(0,s.jsx)(n.li,{children:"Click on the floppy disk icon and the QR code will appear underneath the text field."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(30320).A+"",width:"2052",height:"850"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(99343).A+"",width:"1434",height:"1476"})}),"\n",(0,s.jsx)(n.h2,{id:"clinician-vs-patient-credentials",children:"Clinician vs Patient Credentials"}),"\n",(0,s.jsx)(n.p,{children:"Managing credentials for yourself or others is as follows:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"I am a clinician or researcher and want to manage my own credentials."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Tap the profile icon at top right and select the Manage Credentials option from the drop-down list."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(11776).A+"",width:"864",height:"662"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["I am a clinician or researcher and want to ",(0,s.jsx)(n.strong,{children:"manage the credentials of a patient or participant."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Tap the Edit Password after checking the patient's name."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{src:i(15357).A+"",width:"1925",height:"425"})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(o,{...e})}):o(e)}},57398:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-09-21_at_10.56.36_AM-2b2881d3362d58450a36ff6f6f913a4d.png"},87625:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.26.07_PM-cfc0eb83c0588a3dc0edc8da83ccf0e1.png"},46647:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.27.24_PM-1bfc5391781f336964a42762894d5d08.png"},80597:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.27.40_PM-0c49e9e7bb2ef55bfa03ce28f945a06d.png"},77815:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.27.55_PM-e4682f9ff28853a5a1641e6928bda333.png"},94180:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Screen_Shot_2020-10-02_at_3.28.11_PM-85b6a9111458ad24709f69a74534c99c.png"},11776:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_55-78b704fa0795583fec9d0be4f7243b84.jpeg"},53634:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_61-e8c5bf00d985bae93edfbc966b34a22b.png"},36569:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_62-8d9d14dbf7ff96ba2a8128349b0ebc74.png"},30320:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_63-547c0d0a88be623a091649c0d519aaa9.png"},99343:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_64-c69c21ade0ef0e8641c2fd5d0b49f3ea.png"},15357:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/Untitled_66-f98f18cda775bafe157eafa956429546.png"},16943:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/users_tab-0e262569eb9e13f7ab30e02d75433857.jpg"},28453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>l});var t=i(96540);const s={},a=t.createContext(s);function r(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1a3025ab.ff51e348.js b/assets/js/1a3025ab.3af3525b.js similarity index 98% rename from assets/js/1a3025ab.ff51e348.js rename to assets/js/1a3025ab.3af3525b.js index 86f77833c3..d31a42970a 100644 --- a/assets/js/1a3025ab.ff51e348.js +++ b/assets/js/1a3025ab.3af3525b.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6990],{36789:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"start_here/updating_frequency","title":"Modifying the frequency of a sensor\'s data collection","description":"Sensors collect at default frequencies unless otherwise specified. Modifying the frequency can either increase density (higher Hz) or decrease data burden and storage costs (lower Hz).","source":"@site/docs/06-start_here/15-updating_frequency.md","sourceDirName":"06-start_here","slug":"/start_here/updating_frequency","permalink":"/start_here/updating_frequency","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/15-updating_frequency.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":15,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Checking LAMP battery and data usage","permalink":"/start_here/battery_data_usage"},"next":{"title":"Prerequisites for Deploying the LAMP Platform","permalink":"/deploy/prereqs"}}');var s=n(74848),a=n(28453);const i={},o="Modifying the frequency of a sensor's data collection",d={},c=[];function l(e){const t={a:"a",admonition:"admonition",h1:"h1",header:"header",li:"li",ol:"ol",p:"p",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"modifying-the-frequency-of-a-sensors-data-collection",children:"Modifying the frequency of a sensor's data collection"})}),"\n",(0,s.jsx)(t.p,{children:"Sensors collect at default frequencies unless otherwise specified. Modifying the frequency can either increase density (higher Hz) or decrease data burden and storage costs (lower Hz)."}),"\n",(0,s.jsx)(t.admonition,{type:"warning",children:(0,s.jsxs)(t.p,{children:["Not all sensors have a customizable frequency parameter. Also, the effect of changing the frequency parameter is sensor-dependent. For more information about sensor sampling\ntendencies, see: ",(0,s.jsx)(t.a,{href:"https://docs.lamp.digital/data_science/data_types/sensor_types",children:"https://docs.lamp.digital/data_science/data_types/sensor_types"})]})}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["Navigate to the corresponding API command: ",(0,s.jsx)(t.a,{href:"https://docs.lamp.digital/api/update-a-sensor",children:"https://docs.lamp.digital/api/update-a-sensor"})]}),"\n",(0,s.jsx)(t.li,{children:"Authorize the API tool using your credentials"}),"\n",(0,s.jsx)(t.li,{children:"Change the server address to your domain"}),"\n",(0,s.jsx)(t.li,{children:'In the body, replace the value of the "id" key with the ID of the sensor you want to update'}),"\n",(0,s.jsx)(t.li,{children:'Change the "frequency" field value to the desired frequency (in Hz)'}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(96540);const s={},a=r.createContext(s);function i(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6990],{36789:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"start_here/updating_frequency","title":"Modifying the frequency of a sensor\'s data collection","description":"Sensors collect at default frequencies unless otherwise specified. Modifying the frequency can either increase density (higher Hz) or decrease data burden and storage costs (lower Hz).","source":"@site/docs/06-start_here/15-updating_frequency.md","sourceDirName":"06-start_here","slug":"/start_here/updating_frequency","permalink":"/start_here/updating_frequency","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/15-updating_frequency.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":15,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Checking LAMP battery and data usage","permalink":"/start_here/battery_data_usage"},"next":{"title":"Prerequisites for Deploying the LAMP Platform","permalink":"/deploy/prereqs"}}');var s=n(74848),a=n(28453);const i={},o="Modifying the frequency of a sensor's data collection",d={},c=[];function l(e){const t={a:"a",admonition:"admonition",h1:"h1",header:"header",li:"li",ol:"ol",p:"p",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"modifying-the-frequency-of-a-sensors-data-collection",children:"Modifying the frequency of a sensor's data collection"})}),"\n",(0,s.jsx)(t.p,{children:"Sensors collect at default frequencies unless otherwise specified. Modifying the frequency can either increase density (higher Hz) or decrease data burden and storage costs (lower Hz)."}),"\n",(0,s.jsx)(t.admonition,{type:"warning",children:(0,s.jsxs)(t.p,{children:["Not all sensors have a customizable frequency parameter. Also, the effect of changing the frequency parameter is sensor-dependent. For more information about sensor sampling\ntendencies, see: ",(0,s.jsx)(t.a,{href:"https://docs.lamp.digital/data_science/data_types/sensor_types",children:"https://docs.lamp.digital/data_science/data_types/sensor_types"})]})}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["Navigate to the corresponding API command: ",(0,s.jsx)(t.a,{href:"https://docs.lamp.digital/api/update-a-sensor",children:"https://docs.lamp.digital/api/update-a-sensor"})]}),"\n",(0,s.jsx)(t.li,{children:"Authorize the API tool using your credentials"}),"\n",(0,s.jsx)(t.li,{children:"Change the server address to your domain"}),"\n",(0,s.jsx)(t.li,{children:'In the body, replace the value of the "id" key with the ID of the sensor you want to update'}),"\n",(0,s.jsx)(t.li,{children:'Change the "frequency" field value to the desired frequency (in Hz)'}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(96540);const s={},a=r.createContext(s);function i(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1c0a984b.c1156d5e.js b/assets/js/1c0a984b.d77e93eb.js similarity index 97% rename from assets/js/1c0a984b.c1156d5e.js rename to assets/js/1c0a984b.d77e93eb.js index 5e0ba7e417..1878a67fc9 100644 --- a/assets/js/1c0a984b.c1156d5e.js +++ b/assets/js/1c0a984b.d77e93eb.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6551],{62083:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>n,metadata:()=>i,toc:()=>o});const i=JSON.parse('{"id":"consortium/researcher/create_dbt","title":"Create a DBT Diary Card for a User.","description":"1. From the Activities page, select the [+Add] button.","source":"@site/docs/10-consortium/02-researcher/08-create_dbt.md","sourceDirName":"10-consortium/02-researcher","slug":"/consortium/researcher/create_dbt","permalink":"/consortium/researcher/create_dbt","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/02-researcher/08-create_dbt.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":8,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create a DBT Diary Card","permalink":"/consortium/researcher/DBT/create_dbt_diary"},"next":{"title":"Create a Manage Activity","permalink":"/consortium/researcher/create_manage_activity"}}');var a=r(74848),s=r(28453);const n={},c="Create a DBT Diary Card for a User.",d={},o=[];function l(e){const t={code:"code",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"create-a-dbt-diary-card-for-a-user",children:"Create a DBT Diary Card for a User."})}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["From the Activities page, select the ",(0,a.jsx)(t.code,{children:"[+Add]"})," button."]}),"\n",(0,a.jsxs)(t.li,{children:["Find DBT Diary Card listed under Activities. ",(0,a.jsx)(t.img,{src:r(50442).A+"",width:"2068",height:"1056"})]}),"\n",(0,a.jsx)(t.li,{children:"Add the Activity Title. Otherwise, begin customizing your client\u2019s DBT Diary Card by filling in the relevant fields."}),"\n",(0,a.jsxs)(t.li,{children:["Once you\u2019ve finished, click \u201cSAVE.\u201d ",(0,a.jsx)(t.img,{src:r(92898).A+"",width:"2242",height:"2624"})]}),"\n",(0,a.jsx)(t.li,{children:"Your DBT Diary Card is now customized and saved."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},50442:(e,t,r)=>{r.d(t,{A:()=>i});const i=r.p+"assets/images/add_dbt-7c624506c1dc5d2303af2c4184717db6.jpg"},92898:(e,t,r)=>{r.d(t,{A:()=>i});const i=r.p+"assets/images/save_dbt-d0453704a033a390d1676be4ddf46745.jpg"},28453:(e,t,r)=>{r.d(t,{R:()=>n,x:()=>c});var i=r(96540);const a={},s=i.createContext(a);function n(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:n(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[6551],{62083:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>n,metadata:()=>i,toc:()=>o});const i=JSON.parse('{"id":"consortium/researcher/create_dbt","title":"Create a DBT Diary Card for a User.","description":"1. From the Activities page, select the [+Add] button.","source":"@site/docs/10-consortium/02-researcher/08-create_dbt.md","sourceDirName":"10-consortium/02-researcher","slug":"/consortium/researcher/create_dbt","permalink":"/consortium/researcher/create_dbt","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/02-researcher/08-create_dbt.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":8,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create a DBT Diary Card","permalink":"/consortium/researcher/DBT/create_dbt_diary"},"next":{"title":"Create a Manage Activity","permalink":"/consortium/researcher/create_manage_activity"}}');var a=r(74848),s=r(28453);const n={},c="Create a DBT Diary Card for a User.",d={},o=[];function l(e){const t={code:"code",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.header,{children:(0,a.jsx)(t.h1,{id:"create-a-dbt-diary-card-for-a-user",children:"Create a DBT Diary Card for a User."})}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["From the Activities page, select the ",(0,a.jsx)(t.code,{children:"[+Add]"})," button."]}),"\n",(0,a.jsxs)(t.li,{children:["Find DBT Diary Card listed under Activities. ",(0,a.jsx)(t.img,{src:r(50442).A+"",width:"2068",height:"1056"})]}),"\n",(0,a.jsx)(t.li,{children:"Add the Activity Title. Otherwise, begin customizing your client\u2019s DBT Diary Card by filling in the relevant fields."}),"\n",(0,a.jsxs)(t.li,{children:["Once you\u2019ve finished, click \u201cSAVE.\u201d ",(0,a.jsx)(t.img,{src:r(92898).A+"",width:"2242",height:"2624"})]}),"\n",(0,a.jsx)(t.li,{children:"Your DBT Diary Card is now customized and saved."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},50442:(e,t,r)=>{r.d(t,{A:()=>i});const i=r.p+"assets/images/add_dbt-7c624506c1dc5d2303af2c4184717db6.jpg"},92898:(e,t,r)=>{r.d(t,{A:()=>i});const i=r.p+"assets/images/save_dbt-d0453704a033a390d1676be4ddf46745.jpg"},28453:(e,t,r)=>{r.d(t,{R:()=>n,x:()=>c});var i=r(96540);const a={},s=i.createContext(a);function n(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:n(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1ce659cc.57a29b28.js b/assets/js/1ce659cc.b76f1627.js similarity index 97% rename from assets/js/1ce659cc.57a29b28.js rename to assets/js/1ce659cc.b76f1627.js index dc6d9068fa..d895ded44c 100644 --- a/assets/js/1ce659cc.57a29b28.js +++ b/assets/js/1ce659cc.b76f1627.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4542],{25419:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>n,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"consortium/researcher/create_assess_activity","title":"Create an Assess Activity","description":"How to add an Assess cognitive test from the Patient Profile","source":"@site/docs/10-consortium/02-researcher/06-create_assess_activity.md","sourceDirName":"10-consortium/02-researcher","slug":"/consortium/researcher/create_assess_activity","permalink":"/consortium/researcher/create_assess_activity","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/02-researcher/06-create_assess_activity.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":6,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create a Tip in Learn","permalink":"/consortium/researcher/create_tip"},"next":{"title":"Create and Customize Surveys","permalink":"/consortium/researcher/create_survey"}}');var i=s(74848),a=s(28453);const n={},o="Create an Assess Activity",c={},d=[];function l(e){const t={code:"code",em:"em",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"create-an-assess-activity",children:"Create an Assess Activity"})}),"\n",(0,i.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/-km1ztZgLdY",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.em,{children:"How to add an Assess cognitive test from the Patient Profile"})}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,i.jsxs)(t.li,{children:["Click the ",(0,i.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to add a cognitive test like Jewels to the Assess tab."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{src:s(84175).A+"",width:"680",height:"1058"})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},84175:(e,t,s)=>{s.d(t,{A:()=>r});const r=s.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},28453:(e,t,s)=>{s.d(t,{R:()=>n,x:()=>o});var r=s(96540);const i={},a=r.createContext(i);function n(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:n(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[4542],{25419:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>n,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"consortium/researcher/create_assess_activity","title":"Create an Assess Activity","description":"How to add an Assess cognitive test from the Patient Profile","source":"@site/docs/10-consortium/02-researcher/06-create_assess_activity.md","sourceDirName":"10-consortium/02-researcher","slug":"/consortium/researcher/create_assess_activity","permalink":"/consortium/researcher/create_assess_activity","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/02-researcher/06-create_assess_activity.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":6,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create a Tip in Learn","permalink":"/consortium/researcher/create_tip"},"next":{"title":"Create and Customize Surveys","permalink":"/consortium/researcher/create_survey"}}');var i=s(74848),a=s(28453);const n={},o="Create an Assess Activity",c={},d=[];function l(e){const t={code:"code",em:"em",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"create-an-assess-activity",children:"Create an Assess Activity"})}),"\n",(0,i.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/-km1ztZgLdY",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.em,{children:"How to add an Assess cognitive test from the Patient Profile"})}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,i.jsxs)(t.li,{children:["Click the ",(0,i.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to add a cognitive test like Jewels to the Assess tab."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{src:s(84175).A+"",width:"680",height:"1058"})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},84175:(e,t,s)=>{s.d(t,{A:()=>r});const r=s.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},28453:(e,t,s)=>{s.d(t,{R:()=>n,x:()=>o});var r=s(96540);const i={},a=r.createContext(i);function n(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:n(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1ceaac3e.db61faff.js b/assets/js/1ceaac3e.e1fa651e.js similarity index 98% rename from assets/js/1ceaac3e.db61faff.js rename to assets/js/1ceaac3e.e1fa651e.js index 730d52bb2c..3b1c505b5b 100644 --- a/assets/js/1ceaac3e.db61faff.js +++ b/assets/js/1ceaac3e.e1fa651e.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[737],{28674:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"data_science/cortex/features/secondary/deprecated_features/sms_number","title":"SMS Number","description":"To use this feature, please use Cortex version 2022.03.11 or earlier.","source":"@site/docs/09-data_science/06-cortex/05-features/02-secondary/18-deprecated_features/01-sms_number.md","sourceDirName":"09-data_science/06-cortex/05-features/02-secondary/18-deprecated_features","slug":"/data_science/cortex/features/secondary/deprecated_features/sms_number","permalink":"/data_science/cortex/features/secondary/deprecated_features/sms_number","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/05-features/02-secondary/18-deprecated_features/01-sms_number.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":1,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Trip Duration","permalink":"/data_science/cortex/features/secondary/trip_duration"},"next":{"title":"Bluetooth Device Count","permalink":"/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count"}}');var s=r(74848),a=r(28453);const i={},o="SMS Number",c={},d=[{value:"Description",id:"description",level:4},{value:"Optional or required kwargs",id:"optional-or-required-kwargs",level:4},{value:"Data",id:"data",level:4},{value:"Example",id:"example",level:4}];function l(e){const t={code:"code",em:"em",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"sms-number",children:"SMS Number"})}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.em,{children:(0,s.jsx)(t.strong,{children:"To use this feature, please use Cortex version 2022.03.11 or earlier."})})}),"\n",(0,s.jsx)(t.p,{children:"computed from raw feature: cortex.raw.sms"}),"\n",(0,s.jsx)(t.h4,{id:"description",children:"Description"}),"\n",(0,s.jsx)(t.p,{children:"SMS number sums the number of incoming texts. Note that many types of phones no longer provide SMS data."}),"\n",(0,s.jsx)(t.h4,{id:"optional-or-required-kwargs",children:"Optional or required kwargs"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"start: number"}),": (units: ms) the start time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"end: number"}),": (units: ms) the end time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"resolution: number"}),": (units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"data",children:"Data"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"timestamp: number"}),": (units: ms) the start time of each bin of size ",(0,s.jsx)(t.code,{children:"kwargs['resolution']"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"value: number"}),": (units: None) the number of texts."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:'cortex.secondary.sms_number.sms_number(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000)\n'})}),"\n",(0,s.jsx)(t.p,{children:"Output:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:"{\n 'timestamp': 1607072400000,\n 'duration': 5616000000,\n 'resolution': 86400000,\n 'data': [\n {'timestamp': 1607072400000, 'value': 0},\n {'timestamp': 1607331600000, 'value': 0},\n .\n .\n .\n {'timestamp': 1609232400000, 'value': 3}\n ]\n}\n"})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},28453:(e,t,r)=>{r.d(t,{R:()=>i,x:()=>o});var n=r(96540);const s={},a=n.createContext(s);function i(e){const t=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),n.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[737],{28674:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"data_science/cortex/features/secondary/deprecated_features/sms_number","title":"SMS Number","description":"To use this feature, please use Cortex version 2022.03.11 or earlier.","source":"@site/docs/09-data_science/06-cortex/05-features/02-secondary/18-deprecated_features/01-sms_number.md","sourceDirName":"09-data_science/06-cortex/05-features/02-secondary/18-deprecated_features","slug":"/data_science/cortex/features/secondary/deprecated_features/sms_number","permalink":"/data_science/cortex/features/secondary/deprecated_features/sms_number","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/05-features/02-secondary/18-deprecated_features/01-sms_number.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":1,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Trip Duration","permalink":"/data_science/cortex/features/secondary/trip_duration"},"next":{"title":"Bluetooth Device Count","permalink":"/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count"}}');var s=r(74848),a=r(28453);const i={},o="SMS Number",c={},d=[{value:"Description",id:"description",level:4},{value:"Optional or required kwargs",id:"optional-or-required-kwargs",level:4},{value:"Data",id:"data",level:4},{value:"Example",id:"example",level:4}];function l(e){const t={code:"code",em:"em",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"sms-number",children:"SMS Number"})}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.em,{children:(0,s.jsx)(t.strong,{children:"To use this feature, please use Cortex version 2022.03.11 or earlier."})})}),"\n",(0,s.jsx)(t.p,{children:"computed from raw feature: cortex.raw.sms"}),"\n",(0,s.jsx)(t.h4,{id:"description",children:"Description"}),"\n",(0,s.jsx)(t.p,{children:"SMS number sums the number of incoming texts. Note that many types of phones no longer provide SMS data."}),"\n",(0,s.jsx)(t.h4,{id:"optional-or-required-kwargs",children:"Optional or required kwargs"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"start: number"}),": (units: ms) the start time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"end: number"}),": (units: ms) the end time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"resolution: number"}),": (units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"data",children:"Data"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"timestamp: number"}),": (units: ms) the start time of each bin of size ",(0,s.jsx)(t.code,{children:"kwargs['resolution']"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"value: number"}),": (units: None) the number of texts."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:'cortex.secondary.sms_number.sms_number(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000)\n'})}),"\n",(0,s.jsx)(t.p,{children:"Output:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:"{\n 'timestamp': 1607072400000,\n 'duration': 5616000000,\n 'resolution': 86400000,\n 'data': [\n {'timestamp': 1607072400000, 'value': 0},\n {'timestamp': 1607331600000, 'value': 0},\n .\n .\n .\n {'timestamp': 1609232400000, 'value': 3}\n ]\n}\n"})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},28453:(e,t,r)=>{r.d(t,{R:()=>i,x:()=>o});var n=r(96540);const s={},a=n.createContext(s);function i(e){const t=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),n.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1eed4b54.afc78312.js b/assets/js/1eed4b54.ce94958d.js similarity index 98% rename from assets/js/1eed4b54.afc78312.js rename to assets/js/1eed4b54.ce94958d.js index 938482c435..9872c02b64 100644 --- a/assets/js/1eed4b54.afc78312.js +++ b/assets/js/1eed4b54.ce94958d.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[5067],{39088:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"data_science/cortex/utils/miscellaneous","title":"Miscellaneous","description":"utils.miscfunctions.getos_version","source":"@site/docs/09-data_science/06-cortex/07-utils/07-miscellaneous.md","sourceDirName":"09-data_science/06-cortex/07-utils","slug":"/data_science/cortex/utils/miscellaneous","permalink":"/data_science/cortex/utils/miscellaneous","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/07-utils/07-miscellaneous.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":7,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Notifications","permalink":"/data_science/cortex/utils/notifications"},"next":{"title":"Adding Cortex Features","permalink":"/data_science/cortex/developing_cortex"}}');var i=n(74848),a=n(28453);const o={},c="Miscellaneous",r={},l=[{value:"utils.misc_functions.get_os_version",id:"utilsmisc_functionsget_os_version",level:2},{value:"Args",id:"args",level:4},{value:"Returns",id:"returns",level:4},{value:"Example",id:"example",level:4}];function d(e){const t={code:"code",h1:"h1",h2:"h2",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"miscellaneous",children:"Miscellaneous"})}),"\n",(0,i.jsx)(t.h2,{id:"utilsmisc_functionsget_os_version",children:(0,i.jsx)(t.code,{children:"utils.misc_functions.get_os_version"})}),"\n",(0,i.jsx)(t.p,{children:"Attempts to parse the lamp.analytics data to get the phone OS, version and device type information."}),"\n",(0,i.jsx)(t.h4,{id:"args",children:"Args"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"participant_id"}),": (string) the participant id."]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"returns",children:"Returns"}),"\n",(0,i.jsx)(t.p,{children:'A dictionary comtaining "device_type", "os_version", and "phone_type". Each parameter will be None if it cannot be parsed or if there is no lamp.analytics data.'}),"\n",(0,i.jsx)(t.p,{children:"Please note that the lamp.analytics 'user_agent' information was updated in Spring 2022. This code will not work with older data."}),"\n",(0,i.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:'cortex.utils.misc_functions.get_os_version("U1234567890")\n'})}),"\n",(0,i.jsx)(t.p,{children:"Output:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:'{\n "device_type": "iOS",\n "os_version": "14.7.1",\n "phone_type": "iPhone12,1"\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>c});var s=n(96540);const i={},a=s.createContext(i);function o(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[5067],{39088:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"data_science/cortex/utils/miscellaneous","title":"Miscellaneous","description":"utils.miscfunctions.getos_version","source":"@site/docs/09-data_science/06-cortex/07-utils/07-miscellaneous.md","sourceDirName":"09-data_science/06-cortex/07-utils","slug":"/data_science/cortex/utils/miscellaneous","permalink":"/data_science/cortex/utils/miscellaneous","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/07-utils/07-miscellaneous.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":7,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Notifications","permalink":"/data_science/cortex/utils/notifications"},"next":{"title":"Adding Cortex Features","permalink":"/data_science/cortex/developing_cortex"}}');var i=n(74848),a=n(28453);const o={},c="Miscellaneous",r={},l=[{value:"utils.misc_functions.get_os_version",id:"utilsmisc_functionsget_os_version",level:2},{value:"Args",id:"args",level:4},{value:"Returns",id:"returns",level:4},{value:"Example",id:"example",level:4}];function d(e){const t={code:"code",h1:"h1",h2:"h2",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"miscellaneous",children:"Miscellaneous"})}),"\n",(0,i.jsx)(t.h2,{id:"utilsmisc_functionsget_os_version",children:(0,i.jsx)(t.code,{children:"utils.misc_functions.get_os_version"})}),"\n",(0,i.jsx)(t.p,{children:"Attempts to parse the lamp.analytics data to get the phone OS, version and device type information."}),"\n",(0,i.jsx)(t.h4,{id:"args",children:"Args"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"participant_id"}),": (string) the participant id."]}),"\n"]}),"\n",(0,i.jsx)(t.h4,{id:"returns",children:"Returns"}),"\n",(0,i.jsx)(t.p,{children:'A dictionary comtaining "device_type", "os_version", and "phone_type". Each parameter will be None if it cannot be parsed or if there is no lamp.analytics data.'}),"\n",(0,i.jsx)(t.p,{children:"Please note that the lamp.analytics 'user_agent' information was updated in Spring 2022. This code will not work with older data."}),"\n",(0,i.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:'cortex.utils.misc_functions.get_os_version("U1234567890")\n'})}),"\n",(0,i.jsx)(t.p,{children:"Output:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-markdown",children:'{\n "device_type": "iOS",\n "os_version": "14.7.1",\n "phone_type": "iPhone12,1"\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>c});var s=n(96540);const i={},a=s.createContext(i);function o(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/25c0a742.42e6f8d7.js b/assets/js/25c0a742.7cccbe86.js similarity index 99% rename from assets/js/25c0a742.42e6f8d7.js rename to assets/js/25c0a742.7cccbe86.js index a4e47dedf7..3967a9e5d3 100644 --- a/assets/js/25c0a742.42e6f8d7.js +++ b/assets/js/25c0a742.7cccbe86.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2311],{76341:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"start_here/activities/create_surveys","title":"Create and Customize Surveys","description":"How to Create a Survey from the Patient Profile","source":"@site/docs/06-start_here/06-activities/02-create_surveys.md","sourceDirName":"06-start_here/06-activities","slug":"/start_here/activities/create_surveys","permalink":"/start_here/activities/create_surveys","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/06-activities/02-create_surveys.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":2,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create and Customize Tips","permalink":"/start_here/activities/create_tips"},"next":{"title":"Delete and Schedule Activities","permalink":"/start_here/activities/delete_activities"}}');var n=i(74848),o=i(28453);const r={},a="Create and Customize Surveys",c={},l=[];function d(e){const t={code:"code",em:"em",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"create-and-customize-surveys",children:"Create and Customize Surveys"})}),"\n",(0,n.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/0VkPQBwqLTc",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.em,{children:"How to Create a Survey from the Patient Profile"})}),"\n",(0,n.jsxs)(t.p,{children:["Need some inspiration to create your survey? Browse our ",(0,n.jsx)(t.strong,{children:"Survey Instrument Library"})]}),"\n",(0,n.jsx)(t.p,{children:"Survey instruments and other Activities in the LAMP Platform afford you automatic version control. In other software or when managing \u201cpaper & pencil\u201d data, it is typically difficult, if not impossible, to track changes to survey questions or survey responses when administered with a patient."}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,n.jsxs)(t.li,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to begin. If you would like to edit an existing survey, simply tap on its row in the list instead."]}),"\n",(0,n.jsx)(t.li,{children:"Select Survey Instrument to add a survey to the Assess tab."}),"\n",(0,n.jsx)(t.li,{children:'If you would like to import a survey or activity, click "Import Activities."'}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:i(84175).A+"",width:"680",height:"1058"})}),"\n",(0,n.jsx)(t.h1,{id:"create-a-new-question-for-your-survey",children:"Create a New Question for Your Survey."}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to begin. If you would like to edit an existing survey, simply tap on its row in the list instead."]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Select the study you wish to add the survey to."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Title your survey."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:["Press the blue ",(0,n.jsx)(t.code,{children:"(+)"})," icon at the bottom of the list to create a new question. To go back and edit a question, press its title or question number."]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"You can add description content to each question or option choice that can assist clinicians or patients in their selections. If such the description content field is left empty, it will not be displayed when a question or option choice is presented."}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:i(42301).A+"",width:"1782",height:"860"})}),"\n",(0,n.jsxs)(t.ol,{start:"7",children:["\n",(0,n.jsxs)(t.li,{children:["Please double check and ensure you have no typos or errors when saving the new survey. Once you press the ",(0,n.jsx)(t.code,{children:"[Save]"})," button, you will be returned to the screen displaying the list of Activities in your clinic or study, now with the newly added survey."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"If you need to update your survey to add new questions or remove questions, consider making a new survey instead, to avoid changing the intention of the survey or the analysis of its data."}),"\n",(0,n.jsx)(t.h1,{id:"question-types",children:"Question Types"}),"\n",(0,n.jsx)(t.p,{children:"When selecting the question type, please note the following:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"TEXT"})," questions prompt the individual with a free-form text box within which up to a paragraph content may be written, including emoji characters."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"BOOLEAN"}),' questions prompt the individual with a "Yes" or "No" option; if you require a different true/false scale or custom text, please use ',(0,n.jsx)(t.code,{children:"LIST"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"LIKERT"})," questions prompt the individual with a 4-point scale; the number of points cannot be modified, so if you require a different Likert scale or a custom scale, please use ",(0,n.jsx)(t.code,{children:"LIST"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"LIST"})," questions allow a custom list of options to choose from, each with its own description or anchor, and prompt the individual with a vertical list of radio buttons."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MULTISELECT"})," questions allow a custom list of options from which one or more choice can be made from a vertical list of checkboxes, each with its own description."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"SLIDER"})," questions act exactly like ",(0,n.jsx)(t.code,{children:"LIST"})," questions, except they display a slider of options."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"SHORT ANSWER"})," questions act exactly like ",(0,n.jsx)(t.code,{children:"TEXT"})," questions, except they have a shorter character limit (about a sentence)."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"RATING"})," questions allows the individual to rate their response on a custom like ",(0,n.jsx)(t.code,{children:"LIST"})," questions, except they only display numerical rating options."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"TIME"}),' questions prompt the individual with a box in which only text for hours and minutes "HH',":MM",'" is accepted, either in military time or in standard time,']}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MATRIX"}),' questions allow several survey items to be grouped together in a table with the same set of instructions and answer choices. The first survey item can have any question type except for "Matrix", and subsequent survey items must have the "Matrix" question type.']}),"\n"]}),"\n",(0,n.jsx)(t.h1,{id:"delete-an-individual-option-in-your-questions-list-of-options",children:"Delete an Individual Option in Your Question's List of Options:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:'Press the trash can icon to the right of the outlined "Question Option" text box.'}),"\n",(0,n.jsx)(t.li,{children:"Click the Publish button or press the \u2190 icon at the top left to cancel"}),"\n",(0,n.jsx)(t.li,{children:"Return to the list of existing survey instruments."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},84175:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},42301:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/survey_edit-2af3a87b56d3b8171731adb8f98a0387.jpg"},28453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>a});var s=i(96540);const n={},o=s.createContext(n);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[2311],{76341:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"start_here/activities/create_surveys","title":"Create and Customize Surveys","description":"How to Create a Survey from the Patient Profile","source":"@site/docs/06-start_here/06-activities/02-create_surveys.md","sourceDirName":"06-start_here/06-activities","slug":"/start_here/activities/create_surveys","permalink":"/start_here/activities/create_surveys","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/06-start_here/06-activities/02-create_surveys.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":2,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Create and Customize Tips","permalink":"/start_here/activities/create_tips"},"next":{"title":"Delete and Schedule Activities","permalink":"/start_here/activities/delete_activities"}}');var n=i(74848),o=i(28453);const r={},a="Create and Customize Surveys",c={},l=[];function d(e){const t={code:"code",em:"em",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"create-and-customize-surveys",children:"Create and Customize Surveys"})}),"\n",(0,n.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/0VkPQBwqLTc",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.em,{children:"How to Create a Survey from the Patient Profile"})}),"\n",(0,n.jsxs)(t.p,{children:["Need some inspiration to create your survey? Browse our ",(0,n.jsx)(t.strong,{children:"Survey Instrument Library"})]}),"\n",(0,n.jsx)(t.p,{children:"Survey instruments and other Activities in the LAMP Platform afford you automatic version control. In other software or when managing \u201cpaper & pencil\u201d data, it is typically difficult, if not impossible, to track changes to survey questions or survey responses when administered with a patient."}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,n.jsxs)(t.li,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to begin. If you would like to edit an existing survey, simply tap on its row in the list instead."]}),"\n",(0,n.jsx)(t.li,{children:"Select Survey Instrument to add a survey to the Assess tab."}),"\n",(0,n.jsx)(t.li,{children:'If you would like to import a survey or activity, click "Import Activities."'}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:i(84175).A+"",width:"680",height:"1058"})}),"\n",(0,n.jsx)(t.h1,{id:"create-a-new-question-for-your-survey",children:"Create a New Question for Your Survey."}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:["Click the ",(0,n.jsx)(t.code,{children:"[+ Add]"})," button at the top right of the list to begin. If you would like to edit an existing survey, simply tap on its row in the list instead."]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Select the study you wish to add the survey to."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Title your survey."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:["Press the blue ",(0,n.jsx)(t.code,{children:"(+)"})," icon at the bottom of the list to create a new question. To go back and edit a question, press its title or question number."]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"You can add description content to each question or option choice that can assist clinicians or patients in their selections. If such the description content field is left empty, it will not be displayed when a question or option choice is presented."}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{src:i(42301).A+"",width:"1782",height:"860"})}),"\n",(0,n.jsxs)(t.ol,{start:"7",children:["\n",(0,n.jsxs)(t.li,{children:["Please double check and ensure you have no typos or errors when saving the new survey. Once you press the ",(0,n.jsx)(t.code,{children:"[Save]"})," button, you will be returned to the screen displaying the list of Activities in your clinic or study, now with the newly added survey."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"If you need to update your survey to add new questions or remove questions, consider making a new survey instead, to avoid changing the intention of the survey or the analysis of its data."}),"\n",(0,n.jsx)(t.h1,{id:"question-types",children:"Question Types"}),"\n",(0,n.jsx)(t.p,{children:"When selecting the question type, please note the following:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"TEXT"})," questions prompt the individual with a free-form text box within which up to a paragraph content may be written, including emoji characters."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"BOOLEAN"}),' questions prompt the individual with a "Yes" or "No" option; if you require a different true/false scale or custom text, please use ',(0,n.jsx)(t.code,{children:"LIST"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"LIKERT"})," questions prompt the individual with a 4-point scale; the number of points cannot be modified, so if you require a different Likert scale or a custom scale, please use ",(0,n.jsx)(t.code,{children:"LIST"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"LIST"})," questions allow a custom list of options to choose from, each with its own description or anchor, and prompt the individual with a vertical list of radio buttons."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MULTISELECT"})," questions allow a custom list of options from which one or more choice can be made from a vertical list of checkboxes, each with its own description."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"SLIDER"})," questions act exactly like ",(0,n.jsx)(t.code,{children:"LIST"})," questions, except they display a slider of options."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"SHORT ANSWER"})," questions act exactly like ",(0,n.jsx)(t.code,{children:"TEXT"})," questions, except they have a shorter character limit (about a sentence)."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"RATING"})," questions allows the individual to rate their response on a custom like ",(0,n.jsx)(t.code,{children:"LIST"})," questions, except they only display numerical rating options."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"TIME"}),' questions prompt the individual with a box in which only text for hours and minutes "HH',":MM",'" is accepted, either in military time or in standard time,']}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"MATRIX"}),' questions allow several survey items to be grouped together in a table with the same set of instructions and answer choices. The first survey item can have any question type except for "Matrix", and subsequent survey items must have the "Matrix" question type.']}),"\n"]}),"\n",(0,n.jsx)(t.h1,{id:"delete-an-individual-option-in-your-questions-list-of-options",children:"Delete an Individual Option in Your Question's List of Options:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:'Press the trash can icon to the right of the outlined "Question Option" text box.'}),"\n",(0,n.jsx)(t.li,{children:"Click the Publish button or press the \u2190 icon at the top left to cancel"}),"\n",(0,n.jsx)(t.li,{children:"Return to the list of existing survey instruments."}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},84175:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/activity_menu-2788d6de1850a80a5fa39b0b5e4b0d69.jpg"},42301:(e,t,i)=>{i.d(t,{A:()=>s});const s=i.p+"assets/images/survey_edit-2af3a87b56d3b8171731adb8f98a0387.jpg"},28453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>a});var s=i(96540);const n={},o=s.createContext(n);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/262a60e5.0a2308c0.js b/assets/js/262a60e5.621322f1.js similarity index 98% rename from assets/js/262a60e5.0a2308c0.js rename to assets/js/262a60e5.621322f1.js index badb617a98..a430883e89 100644 --- a/assets/js/262a60e5.0a2308c0.js +++ b/assets/js/262a60e5.621322f1.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[7308],{98883:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>n,default:()=>u,frontMatter:()=>l,metadata:()=>i,toc:()=>s});const i=JSON.parse('{"id":"consortium/joining/webinars","title":"Webinars","description":"Here you will find recordings of all previous webinars in case you were unable to attend.","source":"@site/docs/10-consortium/05-joining/05-webinars.md","sourceDirName":"10-consortium/05-joining","slug":"/consortium/joining/webinars","permalink":"/consortium/joining/webinars","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/05-joining/05-webinars.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":5,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Register your Interest","permalink":"/consortium/joining/register"},"next":{"title":"Researcher Checklist","permalink":"/consortium/researcher/checklist"}}');var o=t(74848),a=t(28453);const l={},n="Webinars",c={},s=[{value:"April 1st, 2021",id:"april-1st-2021",level:2},{value:"March 4th, 2021",id:"march-4th-2021",level:2},{value:"February 4th, 2021",id:"february-4th-2021",level:2},{value:"January 7th, 2021",id:"january-7th-2021",level:2},{value:"December 3rd, 2020",id:"december-3rd-2020",level:2},{value:"November 12th, 2020",id:"november-12th-2020",level:2},{value:"October 10th, 2020",id:"october-10th-2020",level:2},{value:"September 10th, 2020",id:"september-10th-2020",level:2},{value:"August 6th, 2020",id:"august-6th-2020",level:2},{value:"July 22nd, 2020",id:"july-22nd-2020",level:2}];function d(e){const r={h1:"h1",h2:"h2",header:"header",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(r.header,{children:(0,o.jsx)(r.h1,{id:"webinars",children:"Webinars"})}),"\n",(0,o.jsx)(r.p,{children:(0,o.jsx)(r.strong,{children:"Here you will find recordings of all previous webinars in case you were unable to attend."})}),"\n",(0,o.jsx)(r.h2,{id:"april-1st-2021",children:"April 1st, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/xh577pgQ-QY",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"march-4th-2021",children:"March 4th, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/5Ol5jVRClaU",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"february-4th-2021",children:"February 4th, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/WDH6wvFdeB4",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"january-7th-2021",children:"January 7th, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/PF-Y5QVZXL0",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"december-3rd-2020",children:"December 3rd, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/r44r49FzVjA",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"november-12th-2020",children:"November 12th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/F2Hi_ZbpJWA",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"october-10th-2020",children:"October 10th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/XNExU0YlOJs",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"september-10th-2020",children:"September 10th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/KXSGyUFb59A",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"august-6th-2020",children:"August 6th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/fO00wrwCkdQ",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"july-22nd-2020",children:"July 22nd, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/R2IZKtWkJbY",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0})]})}function u(e={}){const{wrapper:r}={...(0,a.R)(),...e.components};return r?(0,o.jsx)(r,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},28453:(e,r,t)=>{t.d(r,{R:()=>l,x:()=>n});var i=t(96540);const o={},a=i.createContext(o);function l(e){const r=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function n(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:l(e.components),i.createElement(a.Provider,{value:r},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[7308],{98883:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>n,default:()=>u,frontMatter:()=>l,metadata:()=>i,toc:()=>s});const i=JSON.parse('{"id":"consortium/joining/webinars","title":"Webinars","description":"Here you will find recordings of all previous webinars in case you were unable to attend.","source":"@site/docs/10-consortium/05-joining/05-webinars.md","sourceDirName":"10-consortium/05-joining","slug":"/consortium/joining/webinars","permalink":"/consortium/joining/webinars","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/05-joining/05-webinars.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":5,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Register your Interest","permalink":"/consortium/joining/register"},"next":{"title":"Researcher Checklist","permalink":"/consortium/researcher/checklist"}}');var o=t(74848),a=t(28453);const l={},n="Webinars",c={},s=[{value:"April 1st, 2021",id:"april-1st-2021",level:2},{value:"March 4th, 2021",id:"march-4th-2021",level:2},{value:"February 4th, 2021",id:"february-4th-2021",level:2},{value:"January 7th, 2021",id:"january-7th-2021",level:2},{value:"December 3rd, 2020",id:"december-3rd-2020",level:2},{value:"November 12th, 2020",id:"november-12th-2020",level:2},{value:"October 10th, 2020",id:"october-10th-2020",level:2},{value:"September 10th, 2020",id:"september-10th-2020",level:2},{value:"August 6th, 2020",id:"august-6th-2020",level:2},{value:"July 22nd, 2020",id:"july-22nd-2020",level:2}];function d(e){const r={h1:"h1",h2:"h2",header:"header",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(r.header,{children:(0,o.jsx)(r.h1,{id:"webinars",children:"Webinars"})}),"\n",(0,o.jsx)(r.p,{children:(0,o.jsx)(r.strong,{children:"Here you will find recordings of all previous webinars in case you were unable to attend."})}),"\n",(0,o.jsx)(r.h2,{id:"april-1st-2021",children:"April 1st, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/xh577pgQ-QY",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"march-4th-2021",children:"March 4th, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/5Ol5jVRClaU",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"february-4th-2021",children:"February 4th, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/WDH6wvFdeB4",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"january-7th-2021",children:"January 7th, 2021"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/PF-Y5QVZXL0",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"december-3rd-2020",children:"December 3rd, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/r44r49FzVjA",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"november-12th-2020",children:"November 12th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/F2Hi_ZbpJWA",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"october-10th-2020",children:"October 10th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/XNExU0YlOJs",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"september-10th-2020",children:"September 10th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/KXSGyUFb59A",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"august-6th-2020",children:"August 6th, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/fO00wrwCkdQ",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,o.jsx)(r.h2,{id:"july-22nd-2020",children:"July 22nd, 2020"}),"\n",(0,o.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/R2IZKtWkJbY",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0})]})}function u(e={}){const{wrapper:r}={...(0,a.R)(),...e.components};return r?(0,o.jsx)(r,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},28453:(e,r,t)=>{t.d(r,{R:()=>l,x:()=>n});var i=t(96540);const o={},a=i.createContext(o);function l(e){const r=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function n(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:l(e.components),i.createElement(a.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/268383b4.29731026.js b/assets/js/268383b4.cf3e2f72.js similarity index 98% rename from assets/js/268383b4.29731026.js rename to assets/js/268383b4.cf3e2f72.js index b50aa3f1e3..9864528330 100644 --- a/assets/js/268383b4.29731026.js +++ b/assets/js/268383b4.cf3e2f72.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[5333],{25848:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"data_science/cortex/features/secondary/healthkit_sleep_duration","title":"Healthkit Sleep Duration","description":"computed from raw feature: cortex.raw.sleep","source":"@site/docs/09-data_science/06-cortex/05-features/02-secondary/08-healthkit_sleep_duration.md","sourceDirName":"09-data_science/06-cortex/05-features/02-secondary","slug":"/data_science/cortex/features/secondary/healthkit_sleep_duration","permalink":"/data_science/cortex/features/secondary/healthkit_sleep_duration","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/05-features/02-secondary/08-healthkit_sleep_duration.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":8,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Game Results","permalink":"/data_science/cortex/features/secondary/game_results"},"next":{"title":"Hometime","permalink":"/data_science/cortex/features/secondary/hometime"}}');var s=n(74848),a=n(28453);const i={},o="Healthkit Sleep Duration",d={},l=[{value:"Description",id:"description",level:4},{value:"Optional or required kwargs",id:"optional-or-required-kwargs",level:4},{value:"Data",id:"data",level:4},{value:"Example",id:"example",level:4}];function c(e){const t={code:"code",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"healthkit-sleep-duration",children:"Healthkit Sleep Duration"})}),"\n",(0,s.jsxs)(t.p,{children:["computed from raw feature: ",(0,s.jsx)(t.code,{children:"cortex.raw.sleep"})]}),"\n",(0,s.jsx)(t.h4,{id:"description",children:"Description"}),"\n",(0,s.jsxs)(t.p,{children:["Healthkit sleep duration sums the durations from the ",(0,s.jsx)(t.code,{children:"lamp.sleep"}),' sensor. The "in_bed", "in_sleep", or "in_awake" durations can be summed. This data only comes from watches. Please refer to section on API Feature Types for more information.']}),"\n",(0,s.jsx)(t.h4,{id:"optional-or-required-kwargs",children:"Optional or required kwargs"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"start"}),": (int, units: ms) the start time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"end"}),": (int, units: ms) the end time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"resolution"}),": (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"duration_type"}),': (str, default: "in bed", options: "in_bed", "in_sleep", "in_awake") the type of durations to sum. If an invalid duration type is passed, None will be returned.']}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"data",children:"Data"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"timestamp"}),": (int, units: ms) the start time of each bin of size ",(0,s.jsx)(t.code,{children:"kwargs['resolution']"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"value"}),": (int, units: ms) the duration."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:'cortex.secondary.healthkit_sleep_duration.healthkit_sleep_duration(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000, duration_type="in_bed")\n'})}),"\n",(0,s.jsx)(t.p,{children:"Output:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:"{\n 'timestamp': 1607072400000,\n 'duration': 5616000000,\n 'resolution': 86400000,\n 'data': [\n {'timestamp': 1607072400000, 'value': None},\n {'timestamp': 1607331600000, 'value': 20000027},\n .\n .\n .\n {'timestamp': 1609232400000, 'value': 30040029}\n ]\n}\n"})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(96540);const s={},a=r.createContext(s);function i(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[5333],{25848:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"data_science/cortex/features/secondary/healthkit_sleep_duration","title":"Healthkit Sleep Duration","description":"computed from raw feature: cortex.raw.sleep","source":"@site/docs/09-data_science/06-cortex/05-features/02-secondary/08-healthkit_sleep_duration.md","sourceDirName":"09-data_science/06-cortex/05-features/02-secondary","slug":"/data_science/cortex/features/secondary/healthkit_sleep_duration","permalink":"/data_science/cortex/features/secondary/healthkit_sleep_duration","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/09-data_science/06-cortex/05-features/02-secondary/08-healthkit_sleep_duration.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":8,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Game Results","permalink":"/data_science/cortex/features/secondary/game_results"},"next":{"title":"Hometime","permalink":"/data_science/cortex/features/secondary/hometime"}}');var s=n(74848),a=n(28453);const i={},o="Healthkit Sleep Duration",d={},l=[{value:"Description",id:"description",level:4},{value:"Optional or required kwargs",id:"optional-or-required-kwargs",level:4},{value:"Data",id:"data",level:4},{value:"Example",id:"example",level:4}];function c(e){const t={code:"code",h1:"h1",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"healthkit-sleep-duration",children:"Healthkit Sleep Duration"})}),"\n",(0,s.jsxs)(t.p,{children:["computed from raw feature: ",(0,s.jsx)(t.code,{children:"cortex.raw.sleep"})]}),"\n",(0,s.jsx)(t.h4,{id:"description",children:"Description"}),"\n",(0,s.jsxs)(t.p,{children:["Healthkit sleep duration sums the durations from the ",(0,s.jsx)(t.code,{children:"lamp.sleep"}),' sensor. The "in_bed", "in_sleep", or "in_awake" durations can be summed. This data only comes from watches. Please refer to section on API Feature Types for more information.']}),"\n",(0,s.jsx)(t.h4,{id:"optional-or-required-kwargs",children:"Optional or required kwargs"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"start"}),": (int, units: ms) the start time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"end"}),": (int, units: ms) the end time."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"resolution"}),": (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"duration_type"}),': (str, default: "in bed", options: "in_bed", "in_sleep", "in_awake") the type of durations to sum. If an invalid duration type is passed, None will be returned.']}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"data",children:"Data"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"timestamp"}),": (int, units: ms) the start time of each bin of size ",(0,s.jsx)(t.code,{children:"kwargs['resolution']"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"value"}),": (int, units: ms) the duration."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:'cortex.secondary.healthkit_sleep_duration.healthkit_sleep_duration(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000, duration_type="in_bed")\n'})}),"\n",(0,s.jsx)(t.p,{children:"Output:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-markdown",children:"{\n 'timestamp': 1607072400000,\n 'duration': 5616000000,\n 'resolution': 86400000,\n 'data': [\n {'timestamp': 1607072400000, 'value': None},\n {'timestamp': 1607331600000, 'value': 20000027},\n .\n .\n .\n {'timestamp': 1609232400000, 'value': 30040029}\n ]\n}\n"})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(96540);const s={},a=r.createContext(s);function i(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/28f4ebf7.cb019596.js b/assets/js/28f4ebf7.7aaa701b.js similarity index 99% rename from assets/js/28f4ebf7.cb019596.js rename to assets/js/28f4ebf7.7aaa701b.js index 0ec6dc99b5..df76652242 100644 --- a/assets/js/28f4ebf7.cb019596.js +++ b/assets/js/28f4ebf7.7aaa701b.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[1391],{449:(A,o,e)=>{e.r(o),e.d(o,{assets:()=>a,contentTitle:()=>r,default:()=>s,frontMatter:()=>B,metadata:()=>i,toc:()=>C});const i=JSON.parse('{"id":"consortium/LAC/Clinicians/emotions","title":"Customize Emotions on a DBT Diary Card","description":"1. Log in to the dashboard and navigate to the Activities tab.","source":"@site/docs/10-consortium/04-LAC/01-Clinicians/09-emotions.md","sourceDirName":"10-consortium/04-LAC/01-Clinicians","slug":"/consortium/LAC/Clinicians/emotions","permalink":"/consortium/LAC/Clinicians/emotions","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/04-LAC/01-Clinicians/09-emotions.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":9,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Customize Target Behaviors on a DBT Diary Card","permalink":"/consortium/LAC/Clinicians/behaviors"},"next":{"title":"Complete a DBT Diary Card for a Client","permalink":"/consortium/LAC/Clinicians/impersonate"}}');var t=e(74848),n=e(28453);const B={},r="Customize Emotions on a DBT Diary Card",a={},C=[];function g(A){const o={code:"code",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",...(0,n.R)(),...A.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.header,{children:(0,t.jsx)(o.h1,{id:"customize-emotions-on-a-dbt-diary-card",children:"Customize Emotions on a DBT Diary Card"})}),"\n",(0,t.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/x4CVaLhFf0o",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,t.jsxs)(o.ol,{children:["\n",(0,t.jsx)(o.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,t.jsxs)(o.li,{children:["Click the ",(0,t.jsx)(o.code,{children:"[+ Add]"})," button at the top right of the list and select DBT Diary Card."]}),"\n",(0,t.jsx)(o.li,{children:"Create a title for the client's DBT Diary Card."}),"\n",(0,t.jsx)(o.li,{children:"Add the life worth living goal."}),"\n",(0,t.jsx)(o.li,{children:"Add target behaviors and target ineffective behavoirs."}),"\n",(0,t.jsxs)(o.li,{children:["Add an emotion by selecting the red ",(0,t.jsx)(o.code,{children:"[+ ADD ITEM]"})," text."]}),"\n",(0,t.jsx)(o.li,{children:"Type the emotion in the text box."}),"\n"]}),"\n",(0,t.jsx)(o.p,{children:(0,t.jsx)(o.img,{src:e(29157).A+"",width:"1826",height:"1442"})}),"\n",(0,t.jsxs)(o.ol,{start:"9",children:["\n",(0,t.jsxs)(o.li,{children:["Save the customized diary card by clicking the blue ",(0,t.jsx)(o.code,{children:"Save"})," button in the bottom right-hand corner."]}),"\n"]}),"\n",(0,t.jsx)(o.p,{children:(0,t.jsx)(o.img,{src:e(77317).A+"",width:"212",height:"116"})})]})}function s(A={}){const{wrapper:o}={...(0,n.R)(),...A.components};return o?(0,t.jsx)(o,{...A,children:(0,t.jsx)(g,{...A})}):g(A)}},29157:(A,o,e)=>{e.d(o,{A:()=>i});const i=e.p+"assets/images/emotions_create-415846548e4599ed4a5d080dd38e27b4.jpg"},77317:(A,o,e)=>{e.d(o,{A:()=>i});const i="data:image/jpeg;base64,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"},28453:(A,o,e)=>{e.d(o,{R:()=>B,x:()=>r});var i=e(96540);const t={},n=i.createContext(t);function B(A){const o=i.useContext(n);return i.useMemo((function(){return"function"==typeof A?A(o):{...o,...A}}),[o,A])}function r(A){let o;return o=A.disableParentContext?"function"==typeof A.components?A.components(t):A.components||t:B(A.components),i.createElement(n.Provider,{value:o},A.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[1391],{449:(A,o,e)=>{e.r(o),e.d(o,{assets:()=>a,contentTitle:()=>r,default:()=>s,frontMatter:()=>B,metadata:()=>i,toc:()=>C});const i=JSON.parse('{"id":"consortium/LAC/Clinicians/emotions","title":"Customize Emotions on a DBT Diary Card","description":"1. Log in to the dashboard and navigate to the Activities tab.","source":"@site/docs/10-consortium/04-LAC/01-Clinicians/09-emotions.md","sourceDirName":"10-consortium/04-LAC/01-Clinicians","slug":"/consortium/LAC/Clinicians/emotions","permalink":"/consortium/LAC/Clinicians/emotions","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/10-consortium/04-LAC/01-Clinicians/09-emotions.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046405000,"sidebarPosition":9,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Customize Target Behaviors on a DBT Diary Card","permalink":"/consortium/LAC/Clinicians/behaviors"},"next":{"title":"Complete a DBT Diary Card for a Client","permalink":"/consortium/LAC/Clinicians/impersonate"}}');var t=e(74848),n=e(28453);const B={},r="Customize Emotions on a DBT Diary Card",a={},C=[];function g(A){const o={code:"code",h1:"h1",header:"header",img:"img",li:"li",ol:"ol",p:"p",...(0,n.R)(),...A.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.header,{children:(0,t.jsx)(o.h1,{id:"customize-emotions-on-a-dbt-diary-card",children:"Customize Emotions on a DBT Diary Card"})}),"\n",(0,t.jsx)("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/x4CVaLhFf0o",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0}),"\n",(0,t.jsxs)(o.ol,{children:["\n",(0,t.jsx)(o.li,{children:"Log in to the dashboard and navigate to the Activities tab."}),"\n",(0,t.jsxs)(o.li,{children:["Click the ",(0,t.jsx)(o.code,{children:"[+ Add]"})," button at the top right of the list and select DBT Diary Card."]}),"\n",(0,t.jsx)(o.li,{children:"Create a title for the client's DBT Diary Card."}),"\n",(0,t.jsx)(o.li,{children:"Add the life worth living goal."}),"\n",(0,t.jsx)(o.li,{children:"Add target behaviors and target ineffective behavoirs."}),"\n",(0,t.jsxs)(o.li,{children:["Add an emotion by selecting the red ",(0,t.jsx)(o.code,{children:"[+ ADD ITEM]"})," text."]}),"\n",(0,t.jsx)(o.li,{children:"Type the emotion in the text box."}),"\n"]}),"\n",(0,t.jsx)(o.p,{children:(0,t.jsx)(o.img,{src:e(29157).A+"",width:"1826",height:"1442"})}),"\n",(0,t.jsxs)(o.ol,{start:"9",children:["\n",(0,t.jsxs)(o.li,{children:["Save the customized diary card by clicking the blue ",(0,t.jsx)(o.code,{children:"Save"})," button in the bottom right-hand corner."]}),"\n"]}),"\n",(0,t.jsx)(o.p,{children:(0,t.jsx)(o.img,{src:e(77317).A+"",width:"212",height:"116"})})]})}function s(A={}){const{wrapper:o}={...(0,n.R)(),...A.components};return o?(0,t.jsx)(o,{...A,children:(0,t.jsx)(g,{...A})}):g(A)}},29157:(A,o,e)=>{e.d(o,{A:()=>i});const i=e.p+"assets/images/emotions_create-415846548e4599ed4a5d080dd38e27b4.jpg"},77317:(A,o,e)=>{e.d(o,{A:()=>i});const i="data:image/jpeg;base64,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"},28453:(A,o,e)=>{e.d(o,{R:()=>B,x:()=>r});var i=e(96540);const t={},n=i.createContext(t);function B(A){const o=i.useContext(n);return i.useMemo((function(){return"function"==typeof A?A(o):{...o,...A}}),[o,A])}function r(A){let o;return o=A.disableParentContext?"function"==typeof A.components?A.components(t):A.components||t:B(A.components),i.createElement(n.Provider,{value:o},A.children)}}}]); \ No newline at end of file diff --git a/assets/js/2e1a6d12.f4aca3bb.js b/assets/js/2e1a6d12.5080e234.js similarity index 99% rename from assets/js/2e1a6d12.f4aca3bb.js rename to assets/js/2e1a6d12.5080e234.js index 412433fe58..4e670f124a 100644 --- a/assets/js/2e1a6d12.f4aca3bb.js +++ b/assets/js/2e1a6d12.5080e234.js @@ -1 +1 @@ -"use strict";(self.webpackChunklamp_platform=self.webpackChunklamp_platform||[]).push([[1533],{58904:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"develop/Training Modules/training-modules","title":"Training Modules","description":"\ud83d\udca1 For the best experience viewing these modules, tap the module icon below and use the [Open as page] button in the top left toolbar.","source":"@site/docs/08-develop/12-Training Modules/01-training-modules.md","sourceDirName":"08-develop/12-Training Modules","slug":"/develop/Training Modules/training-modules","permalink":"/develop/Training Modules/training-modules","draft":false,"unlisted":false,"editUrl":"https://github.com/BIDMCDigitalPsychiatry/LAMP-platform/edit/master/docs/08-develop/12-Training Modules/01-training-modules.md","tags":[],"version":"current","lastUpdatedBy":"Juan","lastUpdatedAt":1732046333000,"sidebarPosition":1,"frontMatter":{},"sidebar":"defaultSidebar","previous":{"title":"Migrating from CouchDB to MongoDB","permalink":"/develop/couchdb-migration"},"next":{"title":"Introduction","permalink":"/data_science/intro"}}');var i=t(74848),r=t(28453);const o={},a="Training Modules",l={},c=[{value:"Resources",id:"resources",level:3},{value:"Everything is a File",id:"everything-is-a-file",level:2},{value:"Directories & Dotfiles",id:"directories--dotfiles",level:3},{value:"Processes",id:"processes",level:3},{value:"Exercises",id:"exercises",level:3},{value:"Regular Expressions",id:"regular-expressions",level:2},{value:"CRON Schedules",id:"cron-schedules",level:3},{value:"File Editors",id:"file-editors",level:2},{value:"Open Source",id:"open-source",level:2},{value:"Important File Formats",id:"important-file-formats",level:2},{value:"Cloud Paradigms",id:"cloud-paradigms",level:2},{value:"Amazon Web Services",id:"amazon-web-services",level:2},{value:"Networking",id:"networking",level:2},{value:"Storage",id:"storage",level:2},{value:"Managing Resources",id:"managing-resources",level:2},{value:"Docker",id:"docker",level:2},{value:"Dockerfiles",id:"dockerfiles",level:2},{value:"Container Orchestration",id:"container-orchestration",level:2},{value:"Docker Compose Files",id:"docker-compose-files",level:2},{value:"Microservices",id:"microservices",level:2},{value:"DevOps",id:"devops",level:2},{value:"Git & GitHub",id:"git--github",level:2},{value:"DevOps Pipeline",id:"devops-pipeline",level:2},{value:"Continuous Testing",id:"continuous-testing",level:3},{value:"Continuous Integration",id:"continuous-integration",level:3},{value:"Continuous Deployment",id:"continuous-deployment",level:3},{value:"GitHub Actions",id:"github-actions",level:2},{value:"Data Lakes & Databases",id:"data-lakes--databases",level:2},{value:"Message Queues",id:"message-queues",level:2},{value:"APIs & SDKs",id:"apis--sdks",level:2},{value:"HTTP & REST",id:"http--rest",level:3},{value:"OpenAPI & JSONSchema",id:"openapi--jsonschema",level:3},{value:"Authentication & Authorization",id:"authentication--authorization",level:3},{value:"Data Frames",id:"data-frames",level:2},{value:"Altair for Visualization",id:"altair-for-visualization",level:2},{value:"Programming Language Internals",id:"programming-language-internals",level:2},{value:"Online Algorithms",id:"online-algorithms",level:2},{value:"Package Managers",id:"package-managers",level:2},{value:"Python Pickles",id:"python-pickles",level:2},{value:"TypeScript",id:"typescript",level:2},{value:"React",id:"react",level:2},{value:"Progressive Web Apps",id:"progressive-web-apps",level:2},{value:"CSS Layout & Animations",id:"css-layout--animations",level:2},{value:"Describing & Debugging Code",id:"describing--debugging-code",level:2},{value:"Code Etiquette",id:"code-etiquette",level:2},{value:"Technical Debt",id:"technical-debt",level:3},{value:"Misc. Principles of Good Code",id:"misc-principles-of-good-code",level:3},{value:"Code Reviews",id:"code-reviews",level:3},{value:"Big Data Analysis",id:"big-data-analysis",level:2},{value:"Algorithmic Analysis",id:"algorithmic-analysis",level:3},{value:"Functional Map-Reduce",id:"functional-map-reduce",level:3},{value:"Asynchronous Functions",id:"asynchronous-functions",level:3},{value:"Programming Fallacies",id:"programming-fallacies",level:2},{value:"Managing Team GitHub Repos",id:"managing-team-github-repos",level:2},{value:"Issue/Project Tracking",id:"issueproject-tracking",level:3},{value:"Using the LAMP Community Forum",id:"using-the-lamp-community-forum",level:3},{value:"Managing Package Deployment",id:"managing-package-deployment",level:2},{value:"iOS & Android App Releases",id:"ios--android-app-releases",level:3},{value:"Utility Scripts (& Automations)",id:"utility-scripts--automations",level:3},{value:"Managing Team AWS Services",id:"managing-team-aws-services",level:2},{value:"Install & configure AWS CLI",id:"install--configure-aws-cli",level:3},{value:"Send an SMS",id:"send-an-sms",level:3},{value:"Send an Email",id:"send-an-email",level:3},{value:"JupyterLab Cloud IDE",id:"jupyterlab-cloud-ide",level:2},{value:"Debugging in Notebooks",id:"debugging-in-notebooks",level:3},{value:"LAMP Platform",id:"lamp-platform",level:2}];function h(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"training-modules",children:"Training Modules"})}),"\n",(0,i.jsx)("aside",{children:(0,i.jsxs)(n.p,{children:["\ud83d\udca1 For the best experience viewing these modules, tap the module icon below and use the ",(0,i.jsx)(n.code,{children:"[Open as page]"})," button in the top left toolbar."]})}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsxs)(n.p,{children:["\u26a0\ufe0f ",(0,i.jsx)(n.strong,{children:"Please be sure to view the video AND read the text/articles."})]}),(0,i.jsxs)(n.p,{children:["Depending on your level of experience, it may take close to two full work days (",(0,i.jsx)(n.strong,{children:"~16 hours"}),") to complete all modules; plan accordingly!"]})]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Name"}),(0,i.jsx)(n.th,{children:"Length"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"UNIX & Shell"}),(0,i.jsx)(n.td,{children:"130 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Cloud Computing"}),(0,i.jsx)(n.td,{children:"80 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Docker & Kubernetes"}),(0,i.jsx)(n.td,{children:"105 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"DevOps & Git"}),(0,i.jsx)(n.td,{children:"55 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Databases & APIs"}),(0,i.jsx)(n.td,{children:"80 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Pandas & Vega"}),(0,i.jsx)(n.td,{children:"150 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TypeScript & React"}),(0,i.jsx)(n.td,{children:"100 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Code Etiquette & Review"}),(0,i.jsx)(n.td,{children:"80 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Team-specific Resources"}),(0,i.jsx)(n.td,{children:"110 minutes"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Markdown"}),(0,i.jsx)(n.td,{})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"resources",children:"Resources"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com",children:(0,i.jsx)(n.strong,{children:"\u2192 Learn any X (programming language, file format, etc.) quickly."})})}),"\n",(0,i.jsx)(n.h1,{id:"unix--shell",children:"UNIX & Shell"}),"\n",(0,i.jsx)(n.p,{children:"Length: 130 minutes"}),"\n",(0,i.jsxs)(n.p,{children:["UNIX is everywhere \u2014 if you're using a Mac, you're on a UNIX computer. Linux is one of the big three operating systems (macOS, Windows, Linux) based on UNIX. Even if you're on a Windows computer, ",(0,i.jsx)(n.a,{href:"https://docs.microsoft.com/en-us/windows/wsl/about",children:"you might still be able to use Linux"}),"! For our purposes, Linux and UNIX are synonymous (often just shortened to ",(0,i.jsx)(n.code,{children:"*nix"}),"). To begin working with a Unix-based system, we need to learn some basics about files and the shell."]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=dDwXnB6XeiA",children:"https://www.youtube.com/watch?v=dDwXnB6XeiA"})}),"\n",(0,i.jsx)(n.h2,{id:"everything-is-a-file",children:"Everything is a File"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~30 minutes"})}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsxs)(n.p,{children:['"',(0,i.jsx)(n.strong,{children:"This is the Unix philosophy"}),': Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface."']}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"UNIX Philosophy [expand to read more]"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Make each [tool] do one thing well"}),". To do a new job, build afresh rather than complicate old [tools] by adding new features."]}),"\n",(0,i.jsxs)(n.li,{children:["Expect the output of every [tool] to become the input to another, as yet unknown, program. ",(0,i.jsx)(n.strong,{children:"Don't clutter output with extraneous information"}),". Avoid stringently columnar or binary input formats. Don't insist on interactive input."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Design and build [tools] to be tried early"}),", ideally within weeks. Don't hesitate to throw away the clumsy parts and rebuild them."]}),"\n",(0,i.jsxs)(n.li,{children:["Use tools in preference [over] unskilled help to lighten a programming task, ",(0,i.jsx)(n.strong,{children:"even if you have to detour to build the tools and expect to throw some of them out"})," after you've finished using them."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["While there are MANY important tools (executables) you can use to automate tasks or diagnose problems, for example, it can be difficult to know HOW exactly to use them. Read the article below to learn more about how to... ",(0,i.jsx)(n.em,{children:"learn more!"})," about these tools you'll encounter."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://blog.nindalf.com/posts/how-to-learn-unix-tools/",children:"How to learn Unix tools"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=42iQKuQodW4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=40&t=40s",children:"https://www.youtube.com/watch?v=42iQKuQodW4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=40&t=40s"})}),"\n",(0,i.jsx)(n.h3,{id:"directories--dotfiles",children:"Directories & Dotfiles"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"All UNIX systems follow the same standardized directory structure (even your Mac, try it!). You will inevitably encounter most of these directories in practice, even if you're working only with data science tools."}),"\n",(0,i.jsxs)(n.p,{children:["When you work with developer tools on the command line, you'll need to configure them on the command line. These configuration are stored in your home directory prefixed with a ",(0,i.jsx)(n.code,{children:"."})," (dot). The most common ones you will see are ",(0,i.jsx)(n.code,{children:".gitignore"}),", ",(0,i.jsx)(n.code,{children:".bashrc"}),", ",(0,i.jsx)(n.code,{children:".env"}),", and ",(0,i.jsx)(n.code,{children:".ssh"})," (a directory of configuration files). ",(0,i.jsx)(n.code,{children:".env"})," files are important for local configuration and testing for the LAMP Platform (or Cortex). Read the article below to learn what a ",(0,i.jsx)(n.code,{children:".bashrc"})," file is."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.journaldev.com/41479/bashrc-file-in-linux",children:"What is .bashrc file in Linux? - JournalDev"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"processes",children:"Processes"}),"\n",(0,i.jsx)(n.p,{children:"This is a list of things your executable code is provided when it's transformed into a live process."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Parent: when you launch a process, it ALWAYS has a parent. A process can also have many children."}),"\n",(0,i.jsxs)(n.li,{children:["Arguments: when you launch a process, you can provide command line arguments to it, which are strings.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["The shell translates this line ",(0,i.jsx)(n.code,{children:"echo hello world"})," \u2192 into this argument list ",(0,i.jsx)(n.code,{children:'["/bin/echo", "hello", "world"]'}),", where the first element of that list is the location of the binary code for the executable."]}),"\n",(0,i.jsxs)(n.li,{children:["Exit Code: when your process exits, it returns a status code (integer) about why it exited (",(0,i.jsx)(n.code,{children:"0"})," indicates success, anything greater than ",(0,i.jsx)(n.code,{children:"0"})," indicates an error)."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Environment Variables: when you launch a process, it ",(0,i.jsx)(n.strong,{children:"inherits"})," a customizable set of variables from the current executing environment.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Current Directory (",(0,i.jsx)(n.code,{children:"cwd"}),"): this informs the process of the current directory it's being executed from."]}),"\n",(0,i.jsxs)(n.li,{children:["Path List (",(0,i.jsx)(n.code,{children:"$PATH"}),"): when you call a binary in the shell (or import some library in Python), it needs to figure out where the executable code is located, and looks up a customizable list of paths to figure that out."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["File Descriptors: these are the default data streams created for your process and are actually virtual files.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Input (",(0,i.jsx)(n.code,{children:"stdin"})," = ",(0,i.jsx)(n.code,{children:"0"}),"): this is an optional input file or stream of data."]}),"\n",(0,i.jsxs)(n.li,{children:["Output (",(0,i.jsx)(n.code,{children:"stdout"})," = ",(0,i.jsx)(n.code,{children:"1"}),"): this is where print statements go!"]}),"\n",(0,i.jsxs)(n.li,{children:["Error (",(0,i.jsx)(n.code,{children:"stderr"})," = ",(0,i.jsx)(n.code,{children:"2"}),"): this is where exceptions and errors go!"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"exercises",children:"Exercises"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~50 minutes"})}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsxs)(n.p,{children:["\u26a0\ufe0f ",(0,i.jsx)(n.a,{href:"https://labs.play-with-docker.com",children:"Follow along here."})]}),(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Play-With-Docker"})," gives you access to a virtual Linux computer so you won't cause harm to your computer."]})]}),"\n",(0,i.jsx)(n.p,{children:"Now you're ready to learn practical examples of these tools; the quick tutorial below will help you learn the basics. You can paste each line into the terminal one by one."}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsxs)(n.p,{children:["\ud83d\udd25 ",(0,i.jsx)(n.strong,{children:"READ EACH COMMENT FIRST BEFORE RUNNING THE COMMAND OR YOU MAY IRREVERSIBLY DAMAGE YOUR COMPUTER!"})]}),(0,i.jsxs)(n.p,{children:['Some commands will require files like "file.txt" to be present \u2014 you can create files in the Terminal using ',(0,i.jsx)(n.code,{children:"touch test.txt"}),"."]})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com/docs/bash/",children:"Learn X in Y minutes Where X=bash"})}),"\n",(0,i.jsxs)(n.p,{children:["This section below contains list of the ",(0,i.jsx)(n.strong,{children:"most useful or important commands our research group uses in real life"}),". Take a look at them and try some of them out!"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=sXQxhojSdZM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=23&t=68s",children:"https://www.youtube.com/watch?v=sXQxhojSdZM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=23&t=68s"})}),"\n",(0,i.jsx)(n.h2,{id:"regular-expressions",children:"Regular Expressions"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~15 minutes"})}),"\n",(0,i.jsxs)(n.p,{children:["RegEx allows you to work with files and strings to find and replace text. On the command line, you can use the old-fashioned ",(0,i.jsx)(n.code,{children:"grep"}),", or instead, the more advanced RipGrep/All (",(0,i.jsx)(n.code,{children:"rg"}),", ",(0,i.jsx)(n.code,{children:"rga"}),") to quickly find and search across entire directories and through binaries, photos, and PDFs!"]}),"\n",(0,i.jsxs)(n.p,{children:["Use ",(0,i.jsx)(n.strong,{children:"RegExr"})," if you need a quick cheatsheet or a tester tool to try out a RegEx before accidentally damaging 150+ files. Yes, this has happened before, and this is why we use Git (which you will learn soon) to roll-back to a previous version."]}),"\n",(0,i.jsxs)(n.p,{children:["\u2192 Exercise: Try to write a RegEx to select filenames ending in ",(0,i.jsx)(n.code,{children:".docx"})," or ",(0,i.jsx)(n.code,{children:".doc"})," (Word files)."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://regexr.com",children:"RegExr: Learn, Build, & Test RegEx"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Solution (Don't peek!)"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"^.*\\.(doc|docx)$"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"cron-schedules",children:"CRON Schedules"}),"\n",(0,i.jsxs)(n.p,{children:["Another kind of \"pattern string\" you'll see a lot is a CRON schedule (and they're used extensively in the LAMP Platform for things like push notification scheduling and automations!). CRON is a system service that runs scripts for you at the schedule you set, using a cron schedule expression. The syntax is quite simple, but once you've read the ",(0,i.jsx)(n.code,{children:"Overview"})," section of the article below, use the interactive expression editor to play around with it."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Cron#Overview",children:"cron - Wikipedia"})}),"\n",(0,i.jsx)(n.p,{children:"\u2192 Try to come up with a cron schedule expression for:"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"At every 30th minute past hour 5 and 15 on every 3rd day-of-month from 1 through 31 in every 3rd month from January through December."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://crontab.guru/#0_0_*_*_*",children:"Crontab.guru - The cron schedule expression editor"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Solution ",(0,i.jsx)(n.strong,{children:"(Don't Peek!)"})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"/30 5,15 1-31/3 1-12/3 *"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=-txKSRn0qeA&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=39&t=1s",children:"https://www.youtube.com/watch?v=-txKSRn0qeA&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=39&t=1s"})}),"\n",(0,i.jsx)(n.h2,{id:"file-editors",children:"File Editors"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~5 minutes"})}),"\n",(0,i.jsx)("aside",{children:(0,i.jsxs)(n.p,{children:["\u26a0\ufe0f ",(0,i.jsx)(n.strong,{children:"Watch until 2:05 only."})]})}),"\n",(0,i.jsxs)(n.p,{children:["Editing files on the command line will require you to learn to use a basic text editor like Vim. ",(0,i.jsxs)(n.strong,{children:["If you're a beginner, ",(0,i.jsx)(n.code,{children:"nano"})," is a much simpler but less featured text editor."]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Another trick is to use ",(0,i.jsx)(n.code,{children:"cat"})," to save a file quickly.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Copy the text you want to paste into the new file."}),"\n",(0,i.jsxs)(n.li,{children:["Execute ",(0,i.jsx)(n.code,{children:"cat > file.txt"}),". (Or use ",(0,i.jsx)(n.code,{children:">>"})," instead of ",(0,i.jsx)(n.code,{children:">"})," to ",(0,i.jsx)(n.strong,{children:"APPEND"})," to an existing file.)"]}),"\n",(0,i.jsx)(n.li,{children:"Paste the text. You'll see your file contents in the terminal now."}),"\n",(0,i.jsxs)(n.li,{children:["To correctly save the file, press ",(0,i.jsx)(n.code,{children:"CTRL-D"}),"."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=tzq4asJegKY&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=37&t=8s",children:"https://www.youtube.com/watch?v=tzq4asJegKY&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=37&t=8s"})}),"\n",(0,i.jsx)(n.h2,{id:"open-source",children:"Open Source"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Though unrelated to actually using Unix, open source is intertwined with almost all the code and tools we use as a team. There's a lot to unpack about how open source works, but knowing how open source, licensing, and 'forking' repositories works is important behind-the-scenes knowledge."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=emFMHH2Bfvo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=44&t=11s",children:"https://www.youtube.com/watch?v=emFMHH2Bfvo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=44&t=11s"})}),"\n",(0,i.jsx)(n.h2,{id:"important-file-formats",children:"Important File Formats"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"While this may appear to have nothing to do with UNIX at first, there are a number of essential file formats that lay the groundwork for the modules to come. In addition to SVG (which is best explained visually), take a brief pass at the syntax for Markdown (human-readable text documents), JSON (human-readable structured data transfer format), and YAML (human-readable configuration file format)."}),"\n",(0,i.jsxs)(n.p,{children:["For ",(0,i.jsx)(n.strong,{children:"Markdown"}),", we also use a documentation generator called Docusaurus that provides additional features, such as embedding tabs, live code blocks, admonitions, automatic table-of-contents, and much more. (",(0,i.jsx)(n.a,{href:"https://www.tablesgenerator.com/markdown_tables",children:"Also, Markdown tables can be quite annoying, so use this GUI tool instead to edit those \u2014 always stick to compact mode."}),")"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com/docs/markdown/",children:"Learn X in Y minutes Where X=markdown"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://docusaurus.io/docs/markdown-features",children:"Markdown Features introduction | Docusaurus"})}),"\n",(0,i.jsx)(n.p,{children:"Whenever possible, avoid JSON for configuration files, only using it as a data storage or transfer protocol; use YAML instead for configuration files."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com/docs/json/",children:"Learn X in Y minutes Where X=json"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com/docs/yaml/",children:"Learn X in Y minutes Where X=yaml"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h1,{id:"useful-linux-commands",children:"Useful Linux Commands"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'#\r\n# SECTION: BASIC COMMANDS\r\n# NOTE: Use CTRL-C (not CMD-C on macOS) to end a process in the console.\r\n# NOTE: Use CTRL-D (sends an "EOF") to quit the shell or console input.\r\n#\r\n\r\n# Get the current UNIX Epoch Timestamp.\r\ndate +%s\r\n# List everything in detail in the current directory.\r\nls -al .\r\n# Create a folder AND all non-existant folders along the way.\r\nmkdir -p ./my/nested/folder\r\n# Create file1.txt\r\ntouch ./my/nested/file1.txt\r\n# Change to a new directory "nested" within "my" within current dir (".").\r\ncd ./my/nested\r\n# Concat\xadenate files ending in .txt (using the * wildcard) and output to console.\r\n# NOTE: This command is most powerful when combined with I/O redirection (below).\r\ncat *.txt\r\n# Copy file1.txt (in ./my/nested) to file2.txt (in a parent directory, "..").\r\ncp file1.txt ../../file1.txt\r\n# DO NOT RUN THIS: Change directory to the parent of the parent of the current dir. \r\ncd ../..\r\n# RUN THIS INSTEAD: Quickly switch back to the directory we were in before.\r\n# NOTE: The - trick works with git checkout as well to switch branches!\r\ncd -\r\n# Get the file type of file1.\r\nfile file1.txt\r\n# Change when file1.txt was last edited.\r\ntouch -d "30 minutes ago" file1.txt\r\n# Move (rename) file1.txt to file2.txt.\r\nmv file1.txt file2.txt\r\n# Paginate file1.txt so it fits on screen and scrolls.\r\nless file1.txt\r\n# Output last lines of file1.txt as it changes in real-time.\r\ntail -f file1.txt\r\n# Delete file1.txt.\r\nrm file1.txt\r\n# Delete a non-empty directory and all of its contents.\r\n# WARNING: This will delete everything in ./my!\r\nrm -rf ./my\r\n# Exit the current shell. (This might close your terminal window too!)\r\nexit\r\n\r\n#\r\n# SECTION: I/O REDIRECTION\r\n# NOTE: "cmd" in this section refers to any command.\r\n#\r\n\r\n# Breaking a comamnd into multiple lines using "\\".\r\ncmd \\\r\n\t--arg1 \\\r\n\t--arg2\r\n# Run cmd1 then cmd2.\r\ncmd1; cmd2\r\n# Run cmd2 ONLY IF cmd1 is successful.\r\ncmd1 && cmd2\r\n# Run cmd2 ONLY IF cmd1 is not successful.\r\ncmd1 || cmd2\r\n# Use file as stdin for cmd (instead of console).\r\n# The file will be created if it does not already exist.\r\n# If the file already exists, its contents will be overridden.\r\ncmd < file\r\n# Use file as stdout for cmd (instead of console).\r\ncmd > file\r\n# Sending stdout to the special file /dev/null discards it.\r\ncmd > /dev/null\r\n# Append stdout to a file.\r\n# This does not overwrite the file if it exists, and instead adds to it.\r\ncmd >> file\r\n# Use file as stderr (error output) for cmd (instead of console).\r\ncmd 2> file\r\n# Send stdout to same place as stderr. (Rarely used.)\r\ncmd 1>&2\r\n# Send stderr to same place as stdout. (Commonly used.)\r\ncmd 2>&1\r\n# Send all output (both stdout and stderr) of cmd to file.\r\ncmd &> file\r\n# Pipe the stdout of cmd1 to cmd2.\r\ncmd1 | cmd2\r\n# Equivalent to the above: use output of cmd1 as file input to cmd2.\r\ncmd2 <(cmd1)\r\n# Pipe the stderr of cmd1 to cmd2.\r\ncmd1 |& cmd2\r\n# The `tee` command sends its stdin to both the file and the console.\r\ncmd | tee output.log\r\n\r\n#\r\n# SECTION: PROCESS MANAGEMENT\r\n# NOTE: "cmd" in this section refers to any command.\r\n#\r\n\r\n# See your shell command history (this is saved in ~/.bash_history too).\r\n# NOTE: This is incredibly useful to backtrack and document in Notion something you did while diagnosing a problem or setting up some code/package.\r\nhistory\r\n# Show current enviro\xadnment variables.\r\nenv\r\n# Output value of $NAME variable. Try it with $HOME or $PATH!\r\n# $PATH = executable search path; $HOME = current user\'s home directory.\r\necho $NAME\r\n# Set $NAME to value. (NOTE THE MISSING DOLLAR SIGN HERE.)\r\nexport NAME=value\r\n# View an interactive system monitor (CPU & RAM usage per-process).\r\ntop\r\n# `ps` prints all processes and `grep cmd` shows ONLY `cmd` specifically.\r\n# NOTE: You need to do this to grab the process ID for below commands.\r\nps -aux | grep cmd\r\n# Kill sends an "interrupt" to a process ID allowing it to exit cleanly.\r\nkill 43273\r\n# The KILL modifier tells the kernel to force-quit the process immediately.\r\nkill -KILL 43273\r\n# Instantly force-quit all processes matching the name "cmd".\r\nkillall cmd\r\n\r\n#\r\n# SECTION: ADVANCED COMMANDS\r\n#\r\n\r\n# Run your last command as root (sudo).\r\n# NOTE: the "!!" shell keyword is replaced by the previously-run command.\r\nsudo !!\r\n# Recursively find files matching a RegEx pattern or string.\r\n# NOTE: If you have RipGrep installed, use "rg" instead of "grep".\r\n# RipGrep: https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md\r\ngrep "hello world" /home/*\r\n# Download a file using cURL or wget (only one may be installed on your system).\r\ncurl -O https://cdn.keycdn.com/css/animate.min.css\r\nwget -o https://cdn.keycdn.com/css/animate.min.css\r\n# cURL allows you to make HTTP requests. "-X" sets the HTTP Method.\r\n# Add new headers with "-H" and send JSON data using "--data".\r\n# NOTE: We use single quotes for data because it won\'t conflict with double quotes.\r\ncurl -X POST \\\r\n\t"api.lamp.digital" \\\r\n\t-H \'Authorization: Basic USERNAME:PASSWORD\' \\\r\n\t-H \'Content-Type: application/json\' \\\r\n\t--data \'{"hello": "world"}\'\r\n# Permissisons: chmod and chown.\r\n# Enable a file to become executable. (Otherwise ./my_script.sh won\'t work.)\r\nchmod +x my_script.sh\r\n# Recursively set permissions of ~/.ssh to 400 (Google chmod to learn more!)\r\nchmod -R 400 ~/.ssh\r\n# Recursively set ownership of /home/username to the username.\r\nchown -R username:username /home/username\r\n# Check the file size of a folder or file (or use wildcard for multiple folders).\r\ndu -sh my_folder_or_file\r\ndu -sh /home/*\r\n# Check the current disk space usage of ALL disks.\r\ndf -hT\r\n# Find large files (greater than 10M, can be modified to your needs).\r\nfind / -size +10M -ls\r\n# Soft-restart the system (the kernel will reboot instead of the hardware.)\r\n# NOTE: NEVER hard-reboot an EC2 instance from the AWS console! Always do this.\r\nreboot\r\n\r\n# \r\n# SECTION: SYSTEM SERVICES\r\n# NOTE: "application" here means any system service. Usually "docker".\r\n#\r\n\r\n# List all system daemons (background services).\r\nsudo systemctl list-units --all\r\n# Check the status of application.\r\nsudo systemctl status application\r\n# Start application in the background.\r\nsudo systemctl start application\r\n# Stop application.\r\nsudo systemctl stop application\r\n# Restart application (if something has broken, for example).\r\nsudo systemctl restart application\r\n# Reload the configuration for application.\r\nsudo systemctl reload application\r\n# Enable or disable application to auto-start on reboots.\r\nsudo systemctl enable application\r\nsudo systemctl disable application\r\n# Check the system logs for application.\r\n# "lines" sets the maximum number of lines we want to view.\r\n# "since" and "unit" set the time boundary for logs.\r\n# "follow" allows you to watch incoming logs in real-time.\r\nsudo journalctl --unit application \\\r\n\t--lines 50 \\\r\n\t--since "09:00" \\\r\n\t--until "1 hour ago" \\\r\n\t--follow\r\n\n'})}),"\n",(0,i.jsx)(n.h1,{id:"cloud-computing",children:"Cloud Computing"}),"\n",(0,i.jsx)(n.p,{children:"Length: 80 minutes"}),"\n",(0,i.jsx)(n.p,{children:"All of the LAMP Platform and all of the Cortex data science we do as a team runs in the Cloud... but what is the Cloud? To put it simply, it's simply \"someone else's computer.\" We pay Amazon Web Services (AWS) to host our computers for us so that, by the click of a button, we can create new computers and hard drives, and also delete them, in exchange for a monthly credit card bill."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=1pBuwKwaHp0&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=9&t=11s",children:"https://www.youtube.com/watch?v=1pBuwKwaHp0&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=9&t=11s"})}),"\n",(0,i.jsx)(n.h2,{id:"cloud-paradigms",children:"Cloud Paradigms"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~25 minutes"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"We're a research group."})," Our focus is on the research we do, the data we collect and the analysis we perform on it. We shouldn't have to focus on running servers and diagnosing network errors and crashes. So we pay someone else to do that for us!"]}),"\n",(0,i.jsx)("aside",{children:(0,i.jsxs)(n.p,{children:["\ud83d\udca1 Our team has used every layer of Amazon's cloud computing in some way, shape, or form (only in the ",(0,i.jsx)(n.code,{children:"us-east-2"}),' region, however). Our collaborators and partners, however, may not use Amazon at all \u2014 some remain "on-prem" (their own servers), or Microsoft Azure, or Google Cloud.\r\n',(0,i.jsx)(n.strong,{children:'The LAMP Platform is architected in a way that remains "platform-agnostic," allowing anyone across these Cloud providers to run LAMP.'})]})}),"\n",(0,i.jsx)("aside",{children:(0,i.jsxs)(n.p,{children:["\ud83d\udca1 ",(0,i.jsx)(n.strong,{children:"Two major concerns arise with Cloud providers: security (IAM) and billing. Managing these for our own tools and systems is still the responsibility of our team."})]})}),"\n",(0,i.jsx)("aside",{children:(0,i.jsxs)(n.p,{children:["\u26a0\ufe0f A ",(0,i.jsx)(n.strong,{children:"MAJOR"})," reason we do our data science in the Cloud is Egress billing: data transfer out of AWS ",(0,i.jsx)(n.strong,{children:"IS EXTREMELY EXPENSIVE"}),". Not to mention, the 25 GB/s uplink to other networking and storage resources would be wasted."]})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=EOIja7yFScs&t=142s",children:"https://www.youtube.com/watch?v=EOIja7yFScs&t=142s"})}),"\n",(0,i.jsxs)(n.p,{children:["Three parts make up cloud infrastructure: ",(0,i.jsx)(n.strong,{children:"Compute, Networking, Storage"}),". Let's imaging an application (or data analysis tool) as a road trip. You'll need some form of transportation to complete your road trip. You can think of:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:'"IaaS" [Infrastructure as a Service] as leasing a car for three years and using it to take several road trips over time.'}),"\n",(0,i.jsx)(n.li,{children:'"PaaS" [Platform as a Service] as renting a car each time you take a road trip.'}),"\n",(0,i.jsx)(n.li,{children:'"FaaS" [Functions as a Service] as taking a taxi from point-to-point during your road trip.'}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Some road trips, such as a tour of New England, may be cheapest and fastest when taking a taxi point-to-point, but others, such as going cross-country twice a year, might be cheapest and most effective when outright leasing a car."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=XRdmfo4M_YA",children:"https://www.youtube.com/watch?v=XRdmfo4M_YA"})}),"\n",(0,i.jsx)(n.h2,{id:"amazon-web-services",children:"Amazon Web Services"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~15 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"The example presented in this video about Computer Vision training is strikingly similar to the kinds of behavioral data analysis we currently (and aim) to do in our research group."}),"\n",(0,i.jsx)(n.p,{children:"We use AWS as our Cloud Provider, and the two guides below will help you better understand which weirdly-named services does what thing, and why (or why not) you should use it."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://hassenchaieb.com/aws-good-parts/",children:"The good parts of AWS - A visual summary"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://expeditedsecurity.com/aws-in-plain-english/",children:"Amazon Web Services In Plain English"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=keeqnciDVOo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=26&t=1s",children:"https://www.youtube.com/watch?v=keeqnciDVOo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=26&t=1s"})}),"\n",(0,i.jsx)(n.h2,{id:"networking",children:"Networking"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~15 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Computers in the Cloud work almost exactly the same as the computer (or phone!) you're using right now to access this page. While multiple programs (executables) can run together easily on a single computer, networking allows multiple computers to talk together."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=2llWuivdS7w",children:"https://www.youtube.com/watch?v=2llWuivdS7w"})}),"\n",(0,i.jsx)(n.p,{children:'From the very basics of "provisioning a node" (aka "renting a computer") in the Cloud, it\'s important to understand how IP addresses and ports work.'}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:"computer"})," also has 65k ",(0,i.jsx)(n.strong,{children:"ports"})," that identify services (i.e. executables) on the system. Many services reserve certain ports, for example, port ",(0,i.jsx)(n.code,{children:"80"})," is reserved for HTTP (websites), and port ",(0,i.jsx)(n.code,{children:"25"})," is reserved for SMTP (email)."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports",children:"List of TCP and UDP port numbers - Wikipedia"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.strong,{children:"socket"})," is the combination of an ",(0,i.jsx)(n.strong,{children:"IP address"})," and a ",(0,i.jsx)(n.strong,{children:"port number"}),". When Computer A (IP ",(0,i.jsx)(n.code,{children:"75.124.87.210"}),") connects to Computer B (IP ",(0,i.jsx)(n.code,{children:"3.12.74.150"}),") to download a web page (port ",(0,i.jsx)(n.code,{children:"80"}),"), a socket is created on both computers to transfer the data."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=JKxlsvZXG7c&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=30&t=16s",children:"https://www.youtube.com/watch?v=JKxlsvZXG7c&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=30&t=16s"})}),"\n",(0,i.jsx)(n.p,{children:"Servers are just computers that are designed to handle public incoming traffic (usually HTTP, aka web pages). Load balancers are just public-facing servers that redirect incoming traffic to different internal protected servers."}),"\n",(0,i.jsx)(n.p,{children:"While this tutorial is about NGINX, we use Traefik, a similar load balancer with more advanced features and easier configuration."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Traefik allows you to serve more than just static files: it can link databases, containers, and other tools to the outside world."}),"\n",(0,i.jsx)(n.li,{children:'Instead of configuration files, Traefik "hooks into" Docker to automatically discover which domain names map to which containers.'}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=5EqAXnNm0FE",children:"https://www.youtube.com/watch?v=5EqAXnNm0FE"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=FLp88DzvtUk",children:"https://www.youtube.com/watch?v=FLp88DzvtUk"})}),"\n",(0,i.jsx)(n.h2,{id:"storage",children:"Storage"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"All data (in the form of files) need to live somewhere to be modified and accessed by a computer."}),"\n",(0,i.jsx)(n.p,{children:"Cloud providers like Amazon (AWS) offer storage in three different ways. Each of these storage types have very different performance, cost, and usage characteristics."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["S3: Object Storage (i.e. databases)","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Cheapest but offers the least performance, and thus is often used to archive petabytes of data. Any number of computers may read or write objects without mounting the drive."}),"\n",(0,i.jsx)("aside",{children:(0,i.jsxs)(n.p,{children:["\ud83d\udca1 ",(0,i.jsx)(n.strong,{children:"Fun fact!"})," Most of the internet (web pages, media such as YouTube, etc.) all run on Object Storage, specifically AWS S3."]})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["EBS: Block Storage (i.e. standard hard drives or SSDs)","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"The most standard and compatible storage, because it emulates a hard drive. You can format the block storage from the operating system and work with files and directories, or just write blocks of raw data to the storage. Only one computer may mount the storage drive at a time."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["EFS: File Storage (i.e. network file shares)","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"The most expensive by far, but allows multiple computers to mount and use the storage drive simultaneously. Emulates a network file share, natively giving the operating system a view of files and directories."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=HmxkYNv1ksg",children:"https://www.youtube.com/watch?v=HmxkYNv1ksg"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Lb-Pnytoi-8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=2&t=87s",children:"https://www.youtube.com/watch?v=Lb-Pnytoi-8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=2&t=87s"})}),"\n",(0,i.jsx)(n.h2,{id:"managing-resources",children:"Managing Resources"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~15 minutes"})}),"\n",(0,i.jsxs)(n.p,{children:["It's really easy to quickly click the shiny buttons on the AWS Management Console and provision hundreds of databases and nodes and thousands of terabytes of storage and so on. ",(0,i.jsx)(n.strong,{children:"You can even provision orbital satellites, robots, and quantum computers!"})]}),"\n",(0,i.jsxs)(n.p,{children:["Therein lies the problem: how do you keep track of all of these things, and how do you make sure that everyone is on the same page about what provisioned service is being used to do what, ",(0,i.jsx)(n.strong,{children:"and especially"}),", how much they all cost per month? What if there are bugs in the application or data analysis code that run up massive bills and they go un-noticed?"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://cloudirregular.substack.com/p/please-fix-the-aws-free-tier-before",children:"Please fix the AWS Free Tier before somebody gets hurt"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h1,{id:"docker--kubernetes",children:"Docker & Kubernetes"}),"\n",(0,i.jsx)(n.p,{children:"Length: 105 minutes"}),"\n",(0,i.jsxs)(n.p,{children:["Containers (Docker) and container orchestration (Kubernetes, Docker Swarm) are a distinct microcosm of cloud computing, and this is where UNIX skills, networking concepts, and more, come together to breathe life into a pile of code through ",(0,i.jsx)(n.code,{children:"Dockerfile"}),"s and ",(0,i.jsx)(n.code,{children:"docker-compose.yml"}),"s."]}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsxs)(n.p,{children:["\ud83d\udca1 **\u2192 Wherever you see or hear ",(0,i.jsx)(n.code,{children:"Kubernetes"}),", replace it in your head with ",(0,i.jsx)(n.code,{children:"Docker Swarm"}),"."]}),(0,i.jsxs)(n.p,{children:["\u26d4\ufe0f Kubernetes** is a container orchestration tool built by Google for Google-scale companies (millions of containers and business-critical data) that requires tremendous expertise to wield correctly.\r\n\u2705 ",(0,i.jsx)(n.strong,{children:"Docker Swarm"})," is a much simpler (with less features) scaled-back version that makes far more sense for data scientists and individual research teams like ours."]})]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Gjnup-PuquQ&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=24&t=2s",children:"https://www.youtube.com/watch?v=Gjnup-PuquQ&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=24&t=2s"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=0qotVMX-J5s",children:"https://www.youtube.com/watch?v=0qotVMX-J5s"})}),"\n",(0,i.jsx)(n.h2,{id:"docker",children:"Docker"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsx)(n.p,{children:'Virtual machines allow you to run multiple virtual computers, like AWS EC2 instances, on top of one hardware computer. They\'re "heavyweight" \u2014 meaning, they require you to virtualize everything from hard disks to USB ports to graphics, to separate one virtual computer from another. Containers follow the same concept, allowing you to run multiple "lightweight" "computers" on top of a shared Linux kernel that only really virtualize the file system. They\'re much lighter, faster, and simpler to use.'}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Your Code"})}),"\n",(0,i.jsx)(n.p,{children:"\u21b3 Docker Container"}),"\n",(0,i.jsx)(n.p,{children:"\u21b3 AWS EC2 Virtual Machine"}),"\n",(0,i.jsx)(n.p,{children:"\u21b3 Hardware Rack"}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=gAkwW2tuIqE&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=25&t=2s",children:"https://www.youtube.com/watch?v=gAkwW2tuIqE&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=25&t=2s"})}),"\n",(0,i.jsx)(n.h2,{id:"dockerfiles",children:"Dockerfiles"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~25 minutes"})}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsxs)(n.p,{children:["\u26a0\ufe0f ",(0,i.jsx)(n.a,{href:"https://labs.play-with-docker.com",children:"Follow along here."})]}),(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Play-With-Docker"})," allows you to use Docker without installing it on your personal computer."]})]}),"\n",(0,i.jsxs)(n.p,{children:["Let's learn how Docker works in practice by creating a container and running it. Follow along with this tutorial (",(0,i.jsx)(n.strong,{children:"BOTH"})," from the video and the link below) to learn how to create and work with ",(0,i.jsx)(n.strong,{children:"Dockerfiles"})," and create containers from them."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://docker.farhan.info/hello-world-in-docker",children:"Hello World in Docker"})}),"\n",(0,i.jsx)(n.p,{children:"Notes about this tutorial:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"git clone "})," to download the example materials to the Play-With-Docker instance."]}),"\n",(0,i.jsxs)(n.li,{children:["When you see URLs like ",(0,i.jsx)(n.code,{children:"http://127.0.0.1:3000/"}),' There\'s an "open port" option at the top of Play-With-Docker that you should use to generate a link to port ',(0,i.jsx)(n.code,{children:"3000"})," instead of actually going to the link specified."]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsxs)(n.p,{children:["You'll likely want to bookmark these two references as they will help you work with ",(0,i.jsx)(n.code,{children:"Dockerfile"}),"s and ",(0,i.jsx)(n.code,{children:"docker-compose.yml"}),"s."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/builder/",children:"Dockerfile reference"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/compose/compose-file/compose-file-v3/",children:"Compose file version 3 reference"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=PziYflu8cB8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=29&t=2s",children:"https://www.youtube.com/watch?v=PziYflu8cB8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=29&t=2s"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=kBF6Bvth0zw",children:"https://www.youtube.com/watch?v=kBF6Bvth0zw"})}),"\n",(0,i.jsx)(n.h2,{id:"container-orchestration",children:"Container Orchestration"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsxs)(n.p,{children:["Orchestration of containers is where things get really interesting, since now with a single ",(0,i.jsx)(n.code,{children:"Dockerfile"}),' we can "shrink-wrap" application environments to run anywhere on any computers. Similarly, a ',(0,i.jsx)(n.code,{children:"docker-compose.yml"})," file (which refers to a type of configuration file and not a filename itself; you can rename them to ",(0,i.jsx)(n.code,{children:"whatever.yml"}),') allows you to "shrink-wrap" and describe how many of these application environments deploy and work together.']}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsxs)(n.p,{children:["\u2192 Why did we choose Docker Swarm over Kubernetes? ",(0,i.jsx)(n.strong,{children:"It's built-in to Docker and takes one command per node to set up the cluster."})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.bugsnag.com/blog/container-orchestration-with-docker-swarm-mode",children:"Lessons learned from using Docker Swarm mode in production | Bugsnag Blog"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/swarm/swarm-tutorial/",children:"Getting started with swarm mode"})}),"\n",(0,i.jsx)(n.p,{children:"\u2192 Docker's command line tools are also compatible with Kubernetes, so using Docker-specific configuration is perfectly acceptable, even if another team wants to deploy the same thing on Kubernetes."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.docker.com/blog/simplifying-kubernetes-with-docker-compose-and-friends/",children:"Simplifying Kubernetes with Docker Compose and Friends - Docker Blog"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=aSrqRSk43lY",children:"https://www.youtube.com/watch?v=aSrqRSk43lY"})}),"\n",(0,i.jsx)(n.h2,{id:"docker-compose-files",children:"Docker Compose Files"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~45 minutes"})}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsxs)(n.p,{children:["\u26a0\ufe0f ",(0,i.jsx)(n.a,{href:"https://labs.play-with-docker.com",children:"Follow along here."})]}),(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Play-With-Docker"})," allows you to use Docker without installing it on your personal computer."]})]}),"\n",(0,i.jsx)(n.p,{children:"While watching these videos, replace the Kubernetes-specific terms with the Docker-specific terms below."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Master Node"})," \u2192 ",(0,i.jsx)(n.code,{children:"Manager Node"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"API Server"})," & ",(0,i.jsx)(n.code,{children:"Kubelet"})," \u2192 ",(0,i.jsx)(n.code,{children:"Docker Daemon"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Pod"})," \u2192 ",(0,i.jsx)(n.code,{children:"Container"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"kubectl"})," \u2192 ",(0,i.jsx)(n.code,{children:"docker"})," (the command line tool)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Load Balancer"})," \u2192 (ignore this; docker does this automatically)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"ClusterIP"})," \u2192 (ignore this; docker does this automatically)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"NodePort"})," \u2192 (",(0,i.jsx)(n.code,{children:"ports"})," parameter for docker ",(0,i.jsx)(n.code,{children:"service"}),")"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Ingress"})," \u2192 (we use ",(0,i.jsx)(n.code,{children:"Traefik"})," which relies on docker ",(0,i.jsx)(n.code,{children:"service"}),")"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=NPFbYpb0I7w",children:"https://www.youtube.com/watch?v=NPFbYpb0I7w"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Once you're finished with these videos"}),", try this practical example in Play-With-Docker or on your computer."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://github.com/mogensen/docker-handson-training/blob/master/3-Docker-swarm/Exercises.md",children:"mogensen/docker-handson-training"})}),"\n",(0,i.jsx)(n.p,{children:"\u2192 To learn how to set up a Traefik ingress, follow along with this guide."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://doc.traefik.io/traefik/providers/docker/",children:"Docker - Traefik"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=CdBtNQZH8a4",children:"https://www.youtube.com/watch?v=CdBtNQZH8a4"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=bvVgP4tw_Hc&t=47s",children:"https://www.youtube.com/watch?v=bvVgP4tw_Hc&t=47s"})}),"\n",(0,i.jsx)(n.h2,{id:"microservices",children:"Microservices"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~15 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Now we've learned how to make containers and how to orchestrate them... but what kind of code goes inside of one of these containers? How exactly ARE they talking to each other?"}),"\n",(0,i.jsx)(n.p,{children:'Where Microservices are flexible and use container orchestration to achieve performance and scalability, Monoliths (i.e. the "old way" of doing things) are installed and run at the IaaS layer, or directly on a computer/node. It\'s difficult to manage, upgrade, maintain, and debug.'}),"\n",(0,i.jsx)(n.p,{children:'The rules below dictate how best to design microservices, and you may recognize how philosophically related these rules are to the Unix philosophy of "everything is a file" and "build flexible, tested, single-function tools." If the UNIX philosophy represents a 2D picture, then microservices are a higher dimension: 3D.'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Rules of Microservices"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"An app that cannot crash. It has a way to fail gracefully but that doesn't involve some downstream coder poking through your call stack."}),"\n",(0,i.jsx)(n.li,{children:"An app that does one and only one useful business function."}),"\n",(0,i.jsx)(n.li,{children:"An app that is composable with other apps from the command line."}),"\n",(0,i.jsx)(n.li,{children:"An app that uses dynamic, free-form, late-bound text streams to talk to other apps."}),"\n",(0,i.jsx)(n.li,{children:"An app that can be reasoned about, modified, or completely replaced by a maintenance programmer many years from now with little or no preparation."}),"\n",(0,i.jsx)(n.li,{children:"The app must have tests."}),"\n",(0,i.jsx)(n.li,{children:"The app must do what the tests say it does."}),"\n",(0,i.jsx)(n.li,{children:"The app cannot do anything that the tests do not cover."}),"\n",(0,i.jsx)(n.li,{children:"These tests exist in a compilation unit separate from the app itself and are in no way coupled to it."}),"\n",(0,i.jsx)(n.li,{children:"When in doubt, think of your compiled app as a pure function running inside a program. That program is a plain, vanilla, default operating system."}),"\n"]}),"\n","\u2014 ",(0,i.jsx)(n.a,{href:"https://danielbmarkham.com/honest-microservices/",children:"Citation"})]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsxs)(n.p,{children:["But while it was once easy to know what your computer was running by using ",(0,i.jsx)(n.code,{children:"top"})," or ",(0,i.jsx)(n.code,{children:"ps"})," and checking logs as raw files, like ",(0,i.jsx)(n.code,{children:"tail -f /var/log/mycoolapp.log"}),", how is it possible to do that with microservices? How do you debug and monitor and maintain them? The answer is: ",(0,i.jsx)(n.strong,{children:"Logging, Monitoring, and Metrics"}),'. Docker fortunately does a very good job of logging for us, and the tools and systems our research group runs are small enough that we don\'t need advanced monitoring (beyond Slack notifications) and metrics (beyond "wow our CPU usage has been at 100% for four days now!").']}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://youtu.be/y8OnoxKotPQ",children:"https://youtu.be/y8OnoxKotPQ"})}),"\n",(0,i.jsxs)(n.p,{children:["Now watch this 3min documentary (and check out the YouTube comments) on Microservices in the real world. Thankfully, the LAMP Platform is not this far gone... ",(0,i.jsx)(n.em,{children:"or is it?"})]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h1,{id:"devops--git",children:"DevOps & Git"}),"\n",(0,i.jsx)(n.p,{children:"Length: 55 minutes"}),"\n",(0,i.jsxs)(n.p,{children:["How do we release software, such as the LAMP Platform, or even our own data analysis (such as feature extraction or analysis methods), in such a way that there are no issues to the patient or research experience? How do multiple scientists or developers collaborate on one large project without stepping on each others' toes and causing massive issues? DevOps is the answer. (",(0,i.jsx)(n.a,{href:"https://gitup.co",children:"By the way, this is a great app if you need to use Git on your Mac."}),")"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:t(20936).A+"",width:"750",height:"459"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=UbtB4sMaaNM",children:"https://www.youtube.com/watch?v=UbtB4sMaaNM"})}),"\n",(0,i.jsx)(n.h2,{id:"devops",children:"DevOps"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~5 minutes"})}),"\n",(0,i.jsx)(n.p,{children:'Short for Development Operations, DevOps is essentially a support and management role for software engineers and data scientists. The DevOps pipeline spans from user stories and user experience to ongoing work items and code changes that land in production environments. The DevOps folks abstract away all of the "hard stuff" and "data plumbing" that you\'re about to learn to allow engineers and data scientists to focus on their work effectively.'}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://aws.amazon.com/devops/what-is-devops/",children:"What is DevOps? - Amazon Web Services (AWS)"})}),"\n",(0,i.jsx)(n.p,{children:"If you haven't had much experience working with complex systems or other peoples' code, you might wonder, \"why is this even important?\" This entertaining article describes the pain that you would have naively gone through (and that our research group once upon a time, aka 2018, did go through)."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://crate.io/a/infrastructure-as-code-part-one/",children:"Infrastructure as Code, Part One - CrateDB"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=hwP7WQkmECE&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=15&t=1s",children:"https://www.youtube.com/watch?v=hwP7WQkmECE&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=15&t=1s"})}),"\n",(0,i.jsx)(n.h2,{id:"git--github",children:"Git & GitHub"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~15 minutes"})}),"\n",(0,i.jsxs)(n.p,{children:["Git is the de facto source code versioning system used by most developers today. All LAMP and Cortex code lives in a Git repository, hosted on GitHub.com. The ",(0,i.jsx)(n.code,{children:"master"}),' branch is the current live code, and "feature branches" contain new features, bug fixes, etc. that need to be merged into the ',(0,i.jsx)(n.code,{children:"master"})," branch after all testing and human code review."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://guides.github.com/introduction/flow/",children:"Understanding the GitHub flow"})}),"\n",(0,i.jsx)(n.p,{children:"\u2192 Once you've watched the video, try out some basic commands here:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://learngitbranching.js.org",children:"Learn Git Branching"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=wpISo9TNjfU",children:"https://www.youtube.com/watch?v=wpISo9TNjfU"})}),"\n",(0,i.jsx)(n.p,{children:"GitHub offers a number of other features beyond just basic version control:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Repository"}),": Git in the Cloud, but with forking and pull requests"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Allows anyone in the world to collaborate on software (or anything else!)"}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"README.md"}),": What is this repo? Explain that here as simple or as complex as you want. ",(0,i.jsx)(n.a,{href:"https://github.com/GitGuardian/gg-shield/blob/main/README.md",children:"Complex example here."})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"LICENSE.md"}),": The legal aspect of open source. ",(0,i.jsx)(n.a,{href:"https://choosealicense.com/",children:"See possible licenses here."})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"SECURITY.md"}),": Explain the responsible disclosure policy for security issues and how to report them."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"CONTRIBUTING.md"}),": helps others understand how to contribute to the repo. ",(0,i.jsxs)(n.a,{href:"https://github.com/atom/atom/blob/master/CONTRIBUTING.md",children:["See ",(0,i.jsx)(n.strong,{children:"AMAZING"})," example here."]})]}),"\n",(0,i.jsx)(n.li,{children:"Issue/PR Templates: For standardized bug reporting and pull request code review processes."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Pages"}),": website hosting (usually for docs, blogs, and other small things)"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Wiki"}),": repo-specific Wikis for documentation"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Issues"}),": track problems and feature requests (and more) per-repo"]}),"\n",(0,i.jsx)(n.p,{children:"\u2192 You'll want to thoroughly understand Issues, and this guide will help you with that."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://guides.github.com/features/issues/",children:"Mastering Issues"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Milestones"}),": track development sprints and work item progress per-repo"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Projects"}),": track issues and pull requests across repositories"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Releases"}),": track important releases and share them with the world safely"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Actions"}),": automated code actions (see below)"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Discussions"}),": similar to issues, but more like a per-repo discussion board"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Insights"}),": security bulletins and collaboration metrics"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=8lGpZkjnkt4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=19&t=3s",children:"https://www.youtube.com/watch?v=8lGpZkjnkt4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=19&t=3s"})}),"\n",(0,i.jsxs)(n.p,{children:["Fun fact: you don't have to use the GitHub website for everything! There's a command line tool companion to ",(0,i.jsx)(n.code,{children:"git"})," called ",(0,i.jsx)(n.code,{children:"gh"})," that can help. Set this up in your Jupyter IDE or local computer."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["(You don't need to follow this guide right now and actually install/use the ",(0,i.jsx)(n.code,{children:"gh"})," tool.)"]})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://cli.github.com/manual/",children:"Manual"})}),"\n",(0,i.jsxs)(n.p,{children:["For example, once you've pushed some code, you can do ",(0,i.jsx)(n.code,{children:"gh pr create"})," right in the command line to send off a pull request and assign a reviewer!"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://cli.github.com/manual/gh_pr_create",children:"gh pr create"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=scEDHsr3APg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=17&t=34s",children:"https://www.youtube.com/watch?v=scEDHsr3APg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=17&t=34s"})}),"\n",(0,i.jsx)(n.h2,{id:"devops-pipeline",children:"DevOps Pipeline"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~25 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Continuous pipelines are the bread and butter of DevOps, automating the entire workflow end-to-end. Remember, the leading cause of problems in code are humans! Automations help simplify and react to code changes or issues dynamically."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"The pipeline explained in a simple diagram:"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:"https://erikbern.com/assets/programming_loops.png",alt:""})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=RYQbmjLgubM",children:"https://www.youtube.com/watch?v=RYQbmjLgubM"})}),"\n",(0,i.jsx)(n.h3,{id:"continuous-testing",children:"Continuous Testing"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"\u2192 Types of Tests:"})}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Unit"}),': Test each individual "unit" of code (such as functions or classes within a project).',"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Unit tests explain what a unit of code is supposed to do and should be narrow in scope, without any dependencies on other code. (For example, ",(0,i.jsx)(n.code,{children:"assert 2 + 2 == 4"})," is a unit test that confirms the behavior of the ",(0,i.jsx)(n.code,{children:"+"})," operator.)"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Snapshot"}),"/",(0,i.jsx)(n.code,{children:"Interaction"}),": Test the user interface in snapshots as well as through user interaction from one component to another. (This is analogous to unit testing for the frontend. ",(0,i.jsx)(n.code,{children:"API"})," testing is the same but for the backend.)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Integration"}),": Test multiple units of code and how they work together, for example, different dependencies, libraries, or multiple peoples' code being merged together."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Regression"}),": Re-test all individual units of code to ensure integration hasn't broken anything in the process."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Acceptance"}),": Test to ensure the entire release of the application (or data analysis notebook) works the way the end users expect it to work.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:'Often, this is a manual step performed by a human (the "release manager") or others on the team to go through a very detailed checklist of each requirement. (Though there are ways to automate this phase as well!)'}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=1er2cjUq1UI",children:"https://www.youtube.com/watch?v=1er2cjUq1UI"})}),"\n",(0,i.jsx)(n.h3,{id:"continuous-integration",children:"Continuous Integration"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=2TTU5BB-k9U",children:"https://www.youtube.com/watch?v=2TTU5BB-k9U"})}),"\n",(0,i.jsx)(n.h3,{id:"continuous-deployment",children:"Continuous Deployment"}),"\n",(0,i.jsx)(n.p,{children:'We use the terms "continuous deployment" and "continuous delivery" interchangeably in our team due to our quite small scale (as opposed to massive companies like Apple or Google...). We use several environments with the LAMP Platform:'}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Development"}),": Each individual data scientist or developer will commit changes to code in a local environment and show that it runs correctly and passes all tests before making a pull request to merge it into the ",(0,i.jsx)(n.code,{children:"master"})," branch.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Developers/scientists will perform code review before approving the pull request as well, allowing a pair of human eyes to triple-check everything."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Staging"}),": This is the environment built on the ",(0,i.jsx)(n.code,{children:"master"})," branch where ",(0,i.jsx)(n.strong,{children:"completed features, improvements, and bug fixes"})," are integrated and tested for quality assurance (QA)."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Production"}),": When staging is QA tested and cleared, a ",(0,i.jsx)(n.code,{children:"git tag"})," is created (i.e. GitHub Release) on that specific commit in the ",(0,i.jsx)(n.code,{children:"master"}),' branch to indicate that "this release is ready to go and usable by others!"',"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["When something hits production, it's going to be used by ",(0,i.jsx)(n.strong,{children:"thousands of patients (with or without serious mental illness), and tens to hundreds of clinicians!"})," You should NEVER be pushing faulty code to production, and AVOID testing anything in production if you can!"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=LNLKZ4Rvk8w",children:"https://www.youtube.com/watch?v=LNLKZ4Rvk8w"})}),"\n",(0,i.jsx)(n.p,{children:"Now enjoy this meme about developer experience vs. testing in production. You'll start off naively testing in production, then learn enough to know that testing in production is terrible, but then eventually realize that life is too short to concern yourself with that, and then you'll test in production anyways. \ud83d\ude42"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:t(9846).A+"",width:"1236",height:"788"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=eB0nUzAI7M8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=18&t=2s",children:"https://www.youtube.com/watch?v=eB0nUzAI7M8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=18&t=2s"})}),"\n",(0,i.jsx)(n.h2,{id:"github-actions",children:"GitHub Actions"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Here you'll see how CI/CD (and testing) is automated in practice across the LAMP Platform and Cortex repositories. You don't need to follow along!"}),"\n",(0,i.jsx)(n.p,{children:'An important note is that most CI/CD pipelines involve "secrets" \u2014 passwords or tokens that allow users to control some kind of tool. For example, an AWS token allows you or a malicious third-party to control ANY AWS service, such as spinning up hundreds of EC2 instances for crypto-mining, causing our team to be charged thousands of dollars.'}),"\n",(0,i.jsx)(n.p,{children:"It's important to keep all secrets separate from code and CI/CD pipelines; we do so through Docker Compose environment variables and GitHub repository secrets, which are only visible to our team."}),"\n",(0,i.jsx)(n.p,{children:"If you would like to follow along on the terminal, see the guide below:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://github.blog/2021-04-15-work-with-github-actions-in-your-terminal-with-github-cli/",children:"Work with GitHub Actions in your terminal with GitHub CLI - The GitHub Blog"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"\u2014 GoatOps.",src:t(82128).A+"",width:"1930",height:"890"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"http://www.goatops.com",children:(0,i.jsx)(n.strong,{children:"\u2014 GoatOps."})})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"http://www.goatops.com/",children:"GoatOps."})," \ud83d\ude42"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h1,{id:"databases--apis",children:"Databases & APIs"}),"\n",(0,i.jsx)(n.p,{children:"Length: 80 minutes"}),"\n",(0,i.jsx)(n.p,{children:"The three main goals of an application, in our flexible definition, are:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Access and manipulate data and perform tasks about the data."}),"\n",(0,i.jsx)(n.li,{children:"Communicate with other tools and services that help it fulfill its role."}),"\n",(0,i.jsx)(n.li,{children:"Externalize itself by allowing clients to speak to it."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"To achieve these goals, we'll need to databases (#1), message queues (#2), and an API (#3)."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=LxcH6z8TFpI&t=118s",children:"https://www.youtube.com/watch?v=LxcH6z8TFpI&t=118s"})}),"\n",(0,i.jsx)(n.h2,{id:"data-lakes--databases",children:"Data Lakes & Databases"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~20 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Data Lakes are a term that originated with Big Data, but essentially refer to a massive collection of different data sources acting as one big database. The LAMP Platform database is actually more of a mini data lake with combined feature store support! Read the article below to better understand what feature stores are, and why feature extraction (i.e. through LAMP Cortex) is important."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.tecton.ai/blog/what-is-a-feature-store/",children:"What is a Feature Store? - Tecton"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=W2Z7fbCLSTw&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=27&t=3s",children:"https://www.youtube.com/watch?v=W2Z7fbCLSTw&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=27&t=3s"})}),"\n",(0,i.jsx)(n.p,{children:'There are MANY different kinds of databases that all work with data in different ways; we primarily use key-value databases (which you may also know in Cloud parlance as Object Storage) and document databases (which hold schema-less JSON data). (We\'ll talk about what "schema" means in the data modeling context later on.)'}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=eIQh02xuVw4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=41&t=2s",children:"https://www.youtube.com/watch?v=eIQh02xuVw4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=41&t=2s"})}),"\n",(0,i.jsxs)(n.p,{children:["While we do not use GraphQL, the LAMP Platform uses a combination of technologies (OpenAPI, JSONSchema, and JSONata) to support what are referred to as ",(0,i.jsx)(n.code,{children:"document transforms"}),". These document transforms are essentially the same as GraphQL queries. It also integrates support for images, files, and ",(0,i.jsx)(n.strong,{children:"dynamic visualizations"})," using Vega, which you'll learn about in a later module."]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=aOE90VAVOcU",children:"https://www.youtube.com/watch?v=aOE90VAVOcU"})}),"\n",(0,i.jsx)(n.p,{children:"While we no longer use CouchDB (as of April 2021), the same principles presented here apply to MongoDB (and AWS DocumentDB, the managed version of MongoDB we use)."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=aj9CDZm0Glc",children:"https://www.youtube.com/watch?v=aj9CDZm0Glc"})}),"\n",(0,i.jsx)(n.h2,{id:"message-queues",children:"Message Queues"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~20 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Message queues are another incredibly important paradigm for designing robust software, across the healthcare systems spectrum. While the LAMP Platform does not use Apache Kafka, it uses NATS, which operates on the same fundamentals."}),"\n",(0,i.jsx)(n.p,{children:'It\'s not hard to understand why we want something like this as part of LAMP: "If a survey is scheduled for 3pm on Friday, send a push notification to the patient\'s mobile device," or "If a patient scores highly on suicidality, send a notification to their physician immediately."'}),"\n",(0,i.jsxs)(n.p,{children:["Read the below article as well ",(0,i.jsxs)(n.strong,{children:["(only until the ",(0,i.jsx)(n.code,{children:"Arguing Semantics"})," section)"]})," to gain a better understanding. The rest of the article is ",(0,i.jsx)(n.strong,{children:"optional"})," if you do want a more comprehensive explanation of specific message queues or Cloud services."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://sudhir.io/the-big-little-guide-to-message-queues/",children:"The Big Little Guide to Message Queues"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=kG-fLp9BTRo&t=213s",children:"https://www.youtube.com/watch?v=kG-fLp9BTRo&t=213s"})}),"\n",(0,i.jsx)(n.h2,{id:"apis--sdks",children:"APIs & SDKs"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~40 minutes"})}),"\n",(0,i.jsx)(n.p,{children:'**Application Programming Interface (API)**s are essentially a set of nouns and verbs that create a vocabulary for a microservice. By documenting and exporting (sharing) your API with others, you enable others to integrate your tools with their tools. For example, to be considered part of the LAMP Platform, a service must speak the "LAMP Protocol," which is an API.'}),"\n",(0,i.jsxs)(n.p,{children:["**Software Development Kit (SDK)**s are a programming language-specific toolbox for handling an API. For example, the LAMP Platform offers the ",(0,i.jsx)(n.code,{children:"LAMP-py"})," SDK for Python, the ",(0,i.jsx)(n.code,{children:"LAMP-r"})," SDK for R, and the ",(0,i.jsx)(n.code,{children:"LAMP-js"})," SDK for JavaScript/TypeScript. All of these SDKs call through to the exact same API, but take care of housekeeping for you and allow you to call methods on native objects and not think about HTTP network calls, JSON serialization, TLS security and so on."]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=-MTSQjw5DrM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=42&t=62s",children:"https://www.youtube.com/watch?v=-MTSQjw5DrM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=42&t=62s"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=lsMQRaeKNDk",children:"https://www.youtube.com/watch?v=lsMQRaeKNDk"})}),"\n",(0,i.jsx)(n.h3,{id:"http--rest",children:"HTTP & REST"}),"\n",(0,i.jsx)(n.p,{children:"The LAMP Protocol relies on HTTP/2.0 (for transporting data between client and server), TLS/1.3 (for encryption in transit), and JSON (for encoding of data payloads)."}),"\n",(0,i.jsx)(n.p,{children:"You do not need to follow along with the NodeJS example in the video, but do realize that this is the exact same setup used by the LAMP Platform's API Server!"}),"\n",(0,i.jsx)(n.p,{children:"Across LAMP-supported languages, there are packages to set up your own web server:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"express"})," for NodeJS"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"flask"})," for Python"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"plumber"})," for R"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:"You'll also need to understand how URLs work, as they are part of the HTTP standard:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://howurls.work/#/",children:"How URLs work?"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:"Enjoy this 20+ year old easter egg in the HTTP standard:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:t(42303).A+"",width:"697",height:"414"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=pRS9LRBgjYg",children:"https://www.youtube.com/watch?v=pRS9LRBgjYg"})}),"\n",(0,i.jsx)(n.h3,{id:"openapi--jsonschema",children:"OpenAPI & JSONSchema"}),"\n",(0,i.jsx)(n.p,{children:"There's no point to an API if no one understands how to use it \u2014 or worse, if it can't be tested and maintained. OpenAPI allows you to do just that by documenting APIs, and even more, like automatically generating SDKs!"}),"\n",(0,i.jsxs)(n.p,{children:["JSONSchema is one part of that, allowing you to document specifically JSON objects. The LAMP Platform uses JSONSchema for its ",(0,i.jsx)(n.code,{children:"*Spec"})," data types, allowing the dashboard to automatically understand, configure, and work with any kind of Activity, Sensor, or Tag. (You'll learn more about this in the LAMP documentation.)"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://json-schema.org/understanding-json-schema/index.html",children:"Understanding JSON Schema - Understanding JSON Schema 7.0 documentation"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=UBUNrFtufWo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=32&t=3s",children:"https://www.youtube.com/watch?v=UBUNrFtufWo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=32&t=3s"})}),"\n",(0,i.jsx)(n.h3,{id:"authentication--authorization",children:"Authentication & Authorization"}),"\n",(0,i.jsx)(n.p,{children:'Authentication refers to the process of understanding "who you are," and authorization is the process of understanding "what you can do." They\'re both required and interlinked, but authentication is a handshake process that happens between the client and server. Once the client authenticates, the server will already know what possible actions the client can take.'}),"\n",(0,i.jsx)(n.p,{children:"There are three main ways to support authentication in an HTTP-based API:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Session"}),": uses browser cookies and saves session data on the server; requires specific login and logout functions to start and stop a session.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"If the password is changed, the server can auto-logout the browser session."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Basic Tokens"}),": a simple username-and-password combination; VERY insecure UNLESS using HTTPS, which encrypts this data.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"If the password is changed, API calls using the old password will fail."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Bearer Tokens"}),": the server generates a token representing an authorized user, with specific parameters and an expiration.","\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["If the password is changed, ",(0,i.jsx)(n.strong,{children:"it is incredibly difficult to handle."})," The only way of doing so is to keep track of a list of disabled tokens until their expiry date has passed."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Another concept is ",(0,i.jsx)(n.strong,{children:"API Tokens"}),', which we will not cover here, but are essentially a "password" that identifies which client code is calling the API. For example, "',(0,i.jsx)(n.code,{children:"John"})," requests ",(0,i.jsx)(n.code,{children:"Patient X data"})," using ",(0,i.jsx)(n.code,{children:"Dashboard"}),'" vs. "',(0,i.jsx)(n.code,{children:"John"})," requests ",(0,i.jsx)(n.code,{children:"Patient X data"})," using ",(0,i.jsx)(n.code,{children:"MyCoolApp"}),'." This is helpful to understand usage patterns and disable bad actors from abusing an API.']}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h1,{id:"pandas--vega",children:"Pandas & Vega"}),"\n",(0,i.jsx)(n.p,{children:"Length: 150 minutes"}),"\n",(0,i.jsx)(n.p,{children:"In our field of research, building and orchestrating applications is just the first phase. It's important to discuss now how clients (ourselves, technically) use what we have established in the last several modules to understand, manipulate, and visualize data in an effective and contextual way. This is true across R, Python, and Javascript/Typescript. Also, there's some important housekeeping lessons to be used for R and Python, such as package management."}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsxs)(n.p,{children:["\ud83d\udca1 This module expects you have experience with either ",(0,i.jsx)(n.a,{href:"https://pandas.pydata.org",children:"Python/Pandas"})," or ",(0,i.jsx)(n.a,{href:"https://www.tidyverse.org/learn/",children:"R/Tidyverse"}),". If you do not, please complete the tutorial(s) below."]}),(0,i.jsx)(n.p,{children:"While R is a supported language, our lab prefers and primarily only uses Python for data analysis. If you are transitioning from R to Python, try the tutorial(s) below."})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.freecodecamp.org/news/learning-python-from-zero-to-hero-120ea540b567/",children:"Learning Python: From Zero to Hero"})}),"\n",(0,i.jsxs)(n.p,{children:["\u2192 The following are reference guides only and do not need to be followed line-by-line: ",(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com/docs/python/",children:"Python"}),", ",(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com/docs/pythonstatcomp/",children:"Statistical Computing in Python"}),", and ",(0,i.jsx)(n.a,{href:"https://learnxinyminutes.com/docs/r/",children:"R script"}),". They are useful if you need to brush up on Python/R or already have programming experience and just need to look something up quickly. Below is another quick reference guide to many basic and advanced Python operations."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://github.com/gto76/python-cheatsheet",children:"gto76/python-cheatsheet"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:t(47310).A+"",width:"791",height:"788"})}),"\n",(0,i.jsx)(n.h2,{id:"data-frames",children:"Data Frames"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~80 min"})}),"\n",(0,i.jsx)(n.p,{children:"Data frames are the most essential data structure used across statistical and scientific computing. You can think of them as an Excel spreadsheet or CSV file, for the most part, but with Python functions and operators to help you mold and manipulate data easily."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://pandas.pydata.org/pandas-docs/stable/user_guide/10min.html#",children:"10 minutes to pandas - pandas 1.2.4 documentation"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"From this User Guide, complete the following chapters:"})}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"10 minutes to pandas"}),"\n",(0,i.jsx)(n.li,{children:"Intro to data structures"}),"\n",(0,i.jsx)(n.li,{children:"Essential basic functionality"}),"\n",(0,i.jsx)(n.li,{children:"Indexing and selecting data"}),"\n",(0,i.jsx)(n.li,{children:"Merge, join, concatenate and compare"}),"\n",(0,i.jsx)(n.li,{children:"Windowing Operations"}),"\n",(0,i.jsx)(n.li,{children:"Time series / date functionality"}),"\n",(0,i.jsx)(n.li,{children:"Time deltas"}),"\n",(0,i.jsx)(n.li,{children:"Frequently Asked Questions"}),"\n",(0,i.jsx)(n.li,{children:"Cookbook"}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"You MUST read and understand this guide below as well!"})}),"\n",(0,i.jsx)(n.p,{children:"Pandas and NumPy allow you to operate on extremely large data sets efficiently using vectorized operations but it is up to the user (you!) to structure your analysis code correctly."}),"\n",(0,i.jsxs)(n.p,{children:["It really does make the difference between ",(0,i.jsx)(n.strong,{children:"15 days and 15 minutes"})," for data processing."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://engineering.upside.com/a-beginners-guide-to-optimizing-pandas-code-for-speed-c09ef2c6a4d6",children:"A Beginner's Guide to Optimizing Pandas Code for Speed"})}),"\n",(0,i.jsxs)(n.p,{children:["Read the article below as well to get a better understanding for why NumPy is so fast \u2014 faster than raw C in some cases (when using ",(0,i.jsx)(n.code,{children:"numexpr"}),")!"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://ggbaker.ca/732/content/pandas-speed.html",children:"NumPy/Pandas Speed"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=AAuPPorsmJc&t=109s",children:"https://www.youtube.com/watch?v=AAuPPorsmJc&t=109s"})}),"\n",(0,i.jsx)(n.h2,{id:"altair-for-visualization",children:"Altair for Visualization"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~40 min"})}),"\n",(0,i.jsxs)(n.p,{children:["To those familiar with ",(0,i.jsx)(n.code,{children:"ggplot2"}),' in R, Altair should be quite familiar as it also implements the same "grammar of graphics." To those familiar with ',(0,i.jsx)(n.code,{children:"matplotlib"})," or ",(0,i.jsx)(n.code,{children:"seaborn"})," in Python, ",(0,i.jsx)(n.strong,{children:"forget what you know and start fresh!"})]}),"\n",(0,i.jsx)(n.p,{children:"An article representation of these few videos is also available:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://eitanlees.github.io/altair-stack/",children:"Understanding The Altair Stack"})}),"\n",(0,i.jsx)(n.p,{children:"\u2192 Once you've watched the video (and/or read the article above), try following along to this getting started guide."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://altair-viz.github.io/getting_started/starting.html",children:"Basic Statistical Visualization - Altair 4.1.0 documentation"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=U7w1XumKK60",children:"https://www.youtube.com/watch?v=U7w1XumKK60"})}),"\n",(0,i.jsx)(n.p,{children:"Once you've watched this video, working with Altair may look a little bit complex. Rest assured, it is by far the simplest visualization library to use. Skim through this article showing code examples across different Python libraries for different types of visualizations:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://dsaber.com/2016/10/02/a-dramatic-tour-through-pythons-data-visualization-landscape-including-ggplot-and-altair/amp/",children:"A Dramatic Tour through Python's Data Visualization Landscape (including ggplot and Altair)"})}),"\n",(0,i.jsxs)(n.p,{children:["\u2192 For a more in depth understanding (optional), ",(0,i.jsx)(n.a,{href:"https://uwdata.github.io/visualization-curriculum/intro.html",children:"check out this guide-book from the team that built Vega/Altair"}),"."]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"To learn how to use UpSetR plots in Altair, see the example code here.",src:t(9689).A+"",width:"1928",height:"1318"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://github.com/hms-dbmi/upset-altair-notebook",children:"To learn how to use UpSetR plots in Altair, see the example code here."})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=LSEPyCqjoAg&t=108s",children:"https://www.youtube.com/watch?v=LSEPyCqjoAg&t=108s"})}),"\n",(0,i.jsxs)(n.p,{children:["Now open the Vega live editor and tap the ",(0,i.jsx)(n.code,{children:"[Examples]"})," button in the top toolbar to play with some sample visualizations. Note that all Vega/Altair visualizations can be interactive and ",(0,i.jsx)(n.strong,{children:"embedded into the LAMP Platform user interfaces"})," or generate static PNG/SVG files."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://vega.github.io/editor/",children:"Editor/IDE for Vega and Vega-Lite"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://altair-viz.github.io/gallery/index.html",children:"Example Gallery - Altair 4.1.0 documentation"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=FSs_JYwnAdI&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=6&t=10s",children:"https://www.youtube.com/watch?v=FSs_JYwnAdI&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=6&t=10s"})}),"\n",(0,i.jsx)(n.h2,{id:"programming-language-internals",children:"Programming Language Internals"}),"\n",(0,i.jsx)(n.p,{children:"While you write code at a very superficial level, there's a lot that goes on behind the scenes, from managing threads on your CPU's many cores to managing heap and stack allocations on system memory (RAM). This video approaches the concept from the perspective of Javascript, but everything here is true of any interpreted language, including Javascript/Typescript, Python, and (especially) R."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["While there is mention of ",(0,i.jsx)(n.code,{children:"prototype-based inheritance"}),", this is largely JS-specific, and most other languages have the familiar model of classes \u2192 objects."]}),"\n",(0,i.jsxs)(n.li,{children:["R as a statistics scripting language surprisingly has several implementations of class-based inheritance, ",(0,i.jsx)(n.a,{href:"https://r6.r-lib.org/articles/Introduction.html",children:"such as S3, S4, and R6, which is preferred"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["Python supports non-blocking async I/O event loops ",(0,i.jsxs)(n.a,{href:"https://docs.python.org/3/library/asyncio.html",children:["through the ",(0,i.jsx)(n.code,{children:"asyncio"})," built-in library"]}),", and R ",(0,i.jsx)(n.a,{href:"https://cran.r-project.org/web/packages/promises/vignettes/intro.html",children:"supports the same through several libraries"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h2,{id:"online-algorithms",children:"Online Algorithms"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsxs)(n.p,{children:["As a minor note, it's important to understand that the kind of data analysis we do, primarily operating on extremely large quantities of time series data, requires a different approach than you may be used to for smaller data sets that may have been able to fit into Excel. Since there's simply no possible way for any the terabytes of LAMP data to fit in system memory, let alone an Excel sheet, we turn to a category of algorithms called ",(0,i.jsx)(n.strong,{children:"Online Algorithms"}),". Read the article below to better understand what they are and why we need them."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://medium.com/analytics-vidhya/data-streams-and-online-machine-learning-in-python-a382e9e8d06a",children:"Data Streams and Online Machine Learning in Python"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h2,{id:"package-managers",children:"Package Managers"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~10 minutes"})}),"\n",(0,i.jsxs)(n.p,{children:["When working with JavaScript or TypeScript, the default package manager, ",(0,i.jsx)(n.code,{children:"npm"})," (Node Package Manager) handles a lot of dependency management and development script workflow for you, avoiding what's called ",(0,i.jsx)(n.strong,{children:'"dependency hell"'}),". In Python, be sure that all packages use the ",(0,i.jsx)(n.strong,{children:"Poetry"})," package manager. (In R, be sure that all packages use the **",(0,i.jsx)(n.a,{href:"https://rstudio.github.io/packrat/",children:"Packrat** package manager"}),".) The tutorial/guide below will explain why a package manager is critical and how to set up and begin using Poetry."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://muttdata.ai/blog/2020/08/21/a-poetic-apology.html",children:"A Poetic Apology"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"Cell 0"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"# First, define a function that performs your API call or download.\r\ndef my_big_scary_download():\r\n\t # TODO: Download 5 TB of data from somewhere like LAMP.\r\n pass\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"Cell 1"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'# Next, check if the cached pickle exists and load it.\r\n# If not, run the download/API call function and then cache it.\r\nimport pickle\r\ntry:\r\n df = pickle.load(open("_cache.pickle", "rb"))\r\nexcept (OSError, IOError) as e:\r\n df = my_big_scary_download()\r\n pickle.dump(df, open("_cache.pickle", "wb"))\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"Cell 2"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:"# Now use the df like any other python variable!\r\ndf.head()\n"})}),"\n",(0,i.jsx)(n.h2,{id:"python-pickles",children:"Python Pickles"}),"\n",(0,i.jsx)("aside",{children:(0,i.jsxs)(n.p,{children:["\ud83d\udd25 ",(0,i.jsx)(n.strong,{children:"AVOID DUMPING DATA TO CSV FILES AT ALL COST!"}),"\r\nThis is a highly inefficient and expensive process (if on AWS like we are, for example)."]})}),"\n",(0,i.jsxs)(n.p,{children:["When performing data analysis on a LARGE quantity of data, either from the LAMP Platform or some other network resource that requires downloading of data, it's bad practice to re-download the same data each and every time your analysis code raises a SyntaxError or some other silly exception. Instead, use ",(0,i.jsx)(n.code,{children:"pickle"}),"s in your Jupyter notebooks to effectively cache and uncache data!"]}),"\n",(0,i.jsx)("aside",{children:(0,i.jsx)(n.p,{children:"\ud83d\udca1 By using two cells like the ones at the left here in all of your Jupyter notebooks, you allow your notebook to work in isolation AND be completely portable. (Meaning, others are able to understand where the data came from and save the cache on their computers too.)"})}),"\n",(0,i.jsx)(n.p,{children:"If you're curious how much better Pickles are, check this comparison out, and also keep in mind that Pickles are native to Python and can embed billions of arbitrary objects into one file, where in contrast for CSV files, you'll need to write custom code for managing thousands of files."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"\u2192 Original Source Article",src:t(68406).A+"",width:"726",height:"379"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://towardsdatascience.com/stop-persisting-pandas-data-frames-in-csvs-f369a6440af5",children:"\u2192 Original Source Article"})}),"\n",(0,i.jsx)(n.p,{children:"\u2192 Two concerns are left as exercises for the reader to complete someday:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"A python function to delete the cached pickle file to re-download everything."}),"\n",(0,i.jsx)(n.li,{children:"A python function to progressively append to the existing pickle instead of deleting and re-downloading data."}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h1,{id:"typescript--react",children:"TypeScript & React"}),"\n",(0,i.jsx)(n.p,{children:"Length: 100 minutes"}),"\n",(0,i.jsx)(n.p,{children:"While Python or R make sense for data analysis and scientific/statistical computing, it's not possible to build a website or app user interface in those languages. And while Python allows you to build backend systems, it may not be the best choice in some cases. This is where TypeScript and React come in \u2014 one unified language for all frontend and backend development. From patient and clinician dashboards, to automated gift card scripts, to cognitive tests, almost everything non-analysis in our research group is written in TypeScript."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:t(71841).A+"",width:"1079",height:"589"})}),"\n",(0,i.jsxs)("aside",{children:[(0,i.jsx)(n.p,{children:"\ud83d\udca1 This module expects you have BASIC experience with Python or a similar programming language. If you do not, please complete the tutorial below."}),(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"The exercises in this module are OPTIONAL if you are not going to be working on interactive data visualization, etc."})}),(0,i.jsx)(n.p,{children:"Please still watch the videos!"})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.freecodecamp.org/news/learning-python-from-zero-to-hero-120ea540b567/",children:"Learning Python: From Zero to Hero"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=9emXNzqCKyg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=7&t=10s",children:"https://www.youtube.com/watch?v=9emXNzqCKyg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=7&t=10s"})}),"\n",(0,i.jsx)(n.h2,{id:"typescript",children:"TypeScript"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~45 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Before we can begin talking about TypeScript, let's begin with a refresher on JavaScript basics. If you'd like a more in-depth written tutorial, the one below will help. (Additionally, Mozilla Developer Network hosts the official/best JS documentation available on the internet.)"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide",children:"JavaScript Guide"})}),"\n",(0,i.jsxs)(n.p,{children:["One major difference between JS and other similar languages (like Python) is the existence of the ",(0,i.jsx)(n.code,{children:"undefined"})," keyword in addition to ",(0,i.jsx)(n.code,{children:"null"})," (or ",(0,i.jsx)(n.code,{children:"None"})," in Python, and ",(0,i.jsx)(n.code,{children:"NULL"})," in R, but R also has the ",(0,i.jsx)(n.code,{children:"NA"})," keyword which is similar)."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.a,{href:"https://2ality.com/2021/01/undefined-null-revisited.html",children:[(0,i.jsx)(n.code,{children:"undefined"})," vs. ",(0,i.jsx)(n.code,{children:"null"})," revisited"]})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=ahCwqrYpIuM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=3&t=35s",children:"https://www.youtube.com/watch?v=ahCwqrYpIuM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=3&t=35s"})}),"\n",(0,i.jsxs)(n.p,{children:["TypeScript is an incremental superset of JavaScript that resolves a ",(0,i.jsx)(n.strong,{children:"significant"})," number of concerns with JS, including the most basic annoyances that cause significant bugs, like ",(0,i.jsx)(n.code,{children:"1 == '1'"})," (in JS, ",(0,i.jsx)(n.code,{children:"string 1 equals number 1"}),", which is horrifying!). For these reasons, ",(0,i.jsx)(n.strong,{children:"we strongly prefer using TypeScript instead of JavaScript dirctly."})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html",children:"Documentation - TypeScript for JavaScript Programmers"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=fsVL_xrYO0w&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=4&t=17s",children:"https://www.youtube.com/watch?v=fsVL_xrYO0w&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=4&t=17s"})}),"\n",(0,i.jsx)(n.p,{children:"Object-oriented and functional programming (aka lambda programming) are two ways to solve problems (which you can find across JS, TS, Python, and R!). The principles of functional programming are: pure functions that do not manipulate state AND immutable data. You'll see these concepts come up in both the context of data analysis but also in the next sections about React for user interface programming."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.youtube.com/watch?v=Tn6-PIqc4UM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=28&t=4s",children:"https://www.youtube.com/watch?v=Tn6-PIqc4UM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=28&t=4s"})}),"\n",(0,i.jsx)(n.h2,{id:"react",children:"React"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"~20 minutes"})}),"\n",(0,i.jsx)(n.p,{children:"Most of the time, user interfaces are built using imperative programming: instantiate some objects that represent visual elements on the screen, when something changes, update properties on those objects, and at the same time, register callbacks on those objects to know when the user does something like press a button or type some text."}),"\n",(0,i.jsxs)(n.p,{children:["React, however, flips that on its head through the declarative programming paradigm. With React, you describe what the user interface should look like in a ",(0,i.jsx)(n.strong,{children:"pure function"})," (a component) and React will help you reconcile the changes."]}),"\n",(0,i.jsx)(n.p,{children:"Once you've finished watching the video, the article below will help you understand how to think differently when working with React \u2014 which is, believe it or not, the critical difference between your patient dashboard loading in 15 minutes vs. 15 seconds."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://reactjs.org/docs/thinking-in-react.html",children:"Thinking in React - React"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsxs)(n.p,{children:['Before we go further, let\'s talk about what makes up a "bare" HTML page. That is, some individual ',(0,i.jsx)(n.code,{children:"my_cool_site.html"})," that would run in the browser on its own without any extra effort!"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.matuzo.at/blog/html-boilerplate/",children:"My current HTML boilerplate"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"At its core, the simplest HTML file would look like this! [expand to view]"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-html",children:'\r\n\r\n\r\n My Cool Website!\r\n \r\n \r\n\t\x3c!-- (This is an HTML comment!) Use Water.CSS to automatically spruce up your website! --\x3e\r\n\t\r\n\t\r\n\r\n\r\n
\r\n\t\t

Hello World!

\r\n\t
\r\n - - + +

Stability & Infrastructure Upgrades

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Improvements

diff --git a/blog/2020/10/05/index.html b/blog/2020/10/05/index.html index e284688a87..909e7d421b 100644 --- a/blog/2020/10/05/index.html +++ b/blog/2020/10/05/index.html @@ -10,8 +10,8 @@ - - + +

General Availability of mindLAMP 2

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/2020/10/15/index.html b/blog/2020/10/15/index.html index 1af0f6b6ac..a3a9c85a62 100644 --- a/blog/2020/10/15/index.html +++ b/blog/2020/10/15/index.html @@ -10,8 +10,8 @@ - - + +

User Experience Upgrades

· 2 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/2020/10/23/index.html b/blog/2020/10/23/index.html index 19ed0ee676..54d05166a3 100644 --- a/blog/2020/10/23/index.html +++ b/blog/2020/10/23/index.html @@ -10,8 +10,8 @@ - - + +

Clinical Customization Updates

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/2020/11/05/index.html b/blog/2020/11/05/index.html index 2a0e771fdf..d1efff3896 100644 --- a/blog/2020/11/05/index.html +++ b/blog/2020/11/05/index.html @@ -10,8 +10,8 @@ - - + +

Stability & Performance Improvements

· 2 min read
Aditya Vaidyam
Division of Digital Psychiatry

Improvements

diff --git a/blog/2020/11/06/index.html b/blog/2020/11/06/index.html index 7fb8ad0da6..42f412d950 100644 --- a/blog/2020/11/06/index.html +++ b/blog/2020/11/06/index.html @@ -10,8 +10,8 @@ - - + +

Ease of Use Improvements

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Bug Fixes

diff --git a/blog/2020/12/01/index.html b/blog/2020/12/01/index.html index 7535bc3a02..f2342a9d76 100644 --- a/blog/2020/12/01/index.html +++ b/blog/2020/12/01/index.html @@ -10,8 +10,8 @@ - - + +

Cortex Visualizations & Activity Updates

· 2 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/2020/12/17/index.html b/blog/2020/12/17/index.html index c38f27c0d7..0fcfc65d3f 100644 --- a/blog/2020/12/17/index.html +++ b/blog/2020/12/17/index.html @@ -10,8 +10,8 @@ - - + +

Ease of Use Improvements

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/2021/01/11/index.html b/blog/2021/01/11/index.html index 988874b87a..987969c341 100644 --- a/blog/2021/01/11/index.html +++ b/blog/2021/01/11/index.html @@ -10,8 +10,8 @@ - - + +

Stability & Performance Improvements

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Improvements

diff --git a/blog/2021/02/12/index.html b/blog/2021/02/12/index.html index a10c8842d9..ecaee5a266 100644 --- a/blog/2021/02/12/index.html +++ b/blog/2021/02/12/index.html @@ -10,8 +10,8 @@ - - + +

Patient Profile & New Cognitive Tests

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/2021/04/01/index.html b/blog/2021/04/01/index.html index 424866afda..12b2d43ce6 100644 --- a/blog/2021/04/01/index.html +++ b/blog/2021/04/01/index.html @@ -10,8 +10,8 @@ - - + + diff --git a/blog/2021/04/22/index.html b/blog/2021/04/22/index.html index 2fee62bd1e..2e9f9acb42 100644 --- a/blog/2021/04/22/index.html +++ b/blog/2021/04/22/index.html @@ -10,8 +10,8 @@ - - + +

Significant Performance Improvements & UI Overhaul

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

This is a significant update -- please review the bolded disclaimer text!

diff --git a/blog/2021/08/09/index.html b/blog/2021/08/09/index.html index f864e87e64..3af743e09e 100644 --- a/blog/2021/08/09/index.html +++ b/blog/2021/08/09/index.html @@ -10,8 +10,8 @@ - - + +

Minor Stability Updates and Bug Fixes

· One min read
Suraj Patel
Division of Digital Psychiatry

Updates

diff --git a/blog/2021/08/25/index.html b/blog/2021/08/25/index.html index f36c0ad4bc..2eb51f462b 100644 --- a/blog/2021/08/25/index.html +++ b/blog/2021/08/25/index.html @@ -10,8 +10,8 @@ - - + +

Visualization & Activity Updates

· One min read
Suraj Patel
Division of Digital Psychiatry

Updates

diff --git a/blog/2021/09/13/index.html b/blog/2021/09/13/index.html index 457c475a53..305539ef97 100644 --- a/blog/2021/09/13/index.html +++ b/blog/2021/09/13/index.html @@ -10,8 +10,8 @@ - - + +

Scheduled Routine mindLAMP AWS Maintenance

· One min read
Suraj Patel
Division of Digital Psychiatry

Hi all,

diff --git a/blog/2021/11/22/index.html b/blog/2021/11/22/index.html index 8f3ba765b8..fb626e047b 100644 --- a/blog/2021/11/22/index.html +++ b/blog/2021/11/22/index.html @@ -10,8 +10,8 @@ - - + +

New, fully functional Clinical-specific use for mindLAMP!

· 2 min read
Suraj Patel
Division of Digital Psychiatry

mindLAMP now features a variety of new features to support a clinical-only team if there is no need for specialized researcher functions or if a simpler and streamlined UI is preferred. See our documentation here for greater details.

diff --git a/blog/2021/12/16/index.html b/blog/2021/12/16/index.html index 6bfc7b44df..f64ecc8d9f 100644 --- a/blog/2021/12/16/index.html +++ b/blog/2021/12/16/index.html @@ -10,8 +10,8 @@ - - + +

New features, stability fixes, and improvements

· 2 min read
Suraj Patel
Division of Digital Psychiatry

New Features

diff --git a/blog/2022/03/07/index.html b/blog/2022/03/07/index.html index 9f81af7e12..bcefb2eef4 100644 --- a/blog/2022/03/07/index.html +++ b/blog/2022/03/07/index.html @@ -10,8 +10,8 @@ - - + +

· One min read
Ashley Meyer
Division of Digital Psychiatry

Features & Improvements

diff --git a/blog/2022/03/22/index.html b/blog/2022/03/22/index.html index 0f2fb6a392..313bf5ea74 100644 --- a/blog/2022/03/22/index.html +++ b/blog/2022/03/22/index.html @@ -10,8 +10,8 @@ - - + +

· One min read

New features and fixes for cortex

diff --git a/blog/2022/04/23/index.html b/blog/2022/04/23/index.html index 37c3bce522..d98036c832 100644 --- a/blog/2022/04/23/index.html +++ b/blog/2022/04/23/index.html @@ -10,8 +10,8 @@ - - + +

Release 2022.4.23

· 6 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features & Improvements

diff --git a/blog/2022/1/11/index.html b/blog/2022/1/11/index.html index 7975ed6134..5930f5893d 100644 --- a/blog/2022/1/11/index.html +++ b/blog/2022/1/11/index.html @@ -10,8 +10,8 @@ - - + +

2022 User Interface Improvements

· One min read
Ashley Meyer
Division of Digital Psychiatry
danger

Server administrators MUST upgrade from :2021 to :2022 versions in the Docker configuration. Please contact us on the forum if there are any questions.

diff --git a/blog/2022/2/15/index.html b/blog/2022/2/15/index.html index 3f2879ad14..eb7fe051d2 100644 --- a/blog/2022/2/15/index.html +++ b/blog/2022/2/15/index.html @@ -10,8 +10,8 @@ - - + +

· 2 min read
Ashley Meyer
Division of Digital Psychiatry

Features & Improvements

diff --git a/blog/archive/index.html b/blog/archive/index.html index 780b6736f6..b0f5fbcb88 100644 --- a/blog/archive/index.html +++ b/blog/archive/index.html @@ -10,8 +10,8 @@ - - + + diff --git a/blog/index.html b/blog/index.html index 5535188890..9eec3a2902 100644 --- a/blog/index.html +++ b/blog/index.html @@ -10,8 +10,8 @@ - - + +

Release 2022.4.23

· 6 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features & Improvements

diff --git a/blog/page/10/index.html b/blog/page/10/index.html index 4a56876372..4f1026c06b 100644 --- a/blog/page/10/index.html +++ b/blog/page/10/index.html @@ -10,8 +10,8 @@ - - + +

Minor Stability Updates and Bug Fixes

· One min read
Suraj Patel
Division of Digital Psychiatry

Updates

diff --git a/blog/page/11/index.html b/blog/page/11/index.html index cdb5d792b4..5f67c14cbc 100644 --- a/blog/page/11/index.html +++ b/blog/page/11/index.html @@ -10,8 +10,8 @@ - - + +

Significant Performance Improvements & UI Overhaul

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

This is a significant update -- please review the bolded disclaimer text!

diff --git a/blog/page/12/index.html b/blog/page/12/index.html index 4b273f6194..acac6f7006 100644 --- a/blog/page/12/index.html +++ b/blog/page/12/index.html @@ -10,8 +10,8 @@ - - + + diff --git a/blog/page/13/index.html b/blog/page/13/index.html index 734b5e92d4..c76bcd6712 100644 --- a/blog/page/13/index.html +++ b/blog/page/13/index.html @@ -10,8 +10,8 @@ - - + +

Patient Profile & New Cognitive Tests

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/page/14/index.html b/blog/page/14/index.html index 35a183f1f3..7fbccfc50c 100644 --- a/blog/page/14/index.html +++ b/blog/page/14/index.html @@ -10,8 +10,8 @@ - - + +

Stability & Performance Improvements

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Improvements

diff --git a/blog/page/15/index.html b/blog/page/15/index.html index fe008bd32f..61e7b9846a 100644 --- a/blog/page/15/index.html +++ b/blog/page/15/index.html @@ -10,8 +10,8 @@ - - + +

Ease of Use Improvements

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/page/16/index.html b/blog/page/16/index.html index 22c08afd40..758eff7f77 100644 --- a/blog/page/16/index.html +++ b/blog/page/16/index.html @@ -10,8 +10,8 @@ - - + +

Cortex Visualizations & Activity Updates

· 2 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/page/17/index.html b/blog/page/17/index.html index b9a297b695..718e283a32 100644 --- a/blog/page/17/index.html +++ b/blog/page/17/index.html @@ -10,8 +10,8 @@ - - + +

Ease of Use Improvements

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Bug Fixes

diff --git a/blog/page/18/index.html b/blog/page/18/index.html index 9ed3250018..495e388589 100644 --- a/blog/page/18/index.html +++ b/blog/page/18/index.html @@ -10,8 +10,8 @@ - - + +

Stability & Performance Improvements

· 2 min read
Aditya Vaidyam
Division of Digital Psychiatry

Improvements

diff --git a/blog/page/19/index.html b/blog/page/19/index.html index 0b6e75beda..0b9d66c508 100644 --- a/blog/page/19/index.html +++ b/blog/page/19/index.html @@ -10,8 +10,8 @@ - - + +

Clinical Customization Updates

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/page/2/index.html b/blog/page/2/index.html index 09cc647b79..11ccb1c9fa 100644 --- a/blog/page/2/index.html +++ b/blog/page/2/index.html @@ -10,8 +10,8 @@ - - + +

· One min read

New features and fixes for cortex

diff --git a/blog/page/20/index.html b/blog/page/20/index.html index 9369357670..23048cadbd 100644 --- a/blog/page/20/index.html +++ b/blog/page/20/index.html @@ -10,8 +10,8 @@ - - + +

User Experience Upgrades

· 2 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/page/21/index.html b/blog/page/21/index.html index 1f53b55555..c2777ebd6f 100644 --- a/blog/page/21/index.html +++ b/blog/page/21/index.html @@ -10,8 +10,8 @@ - - + +

General Availability of mindLAMP 2

· 3 min read
Aditya Vaidyam
Division of Digital Psychiatry

Features

diff --git a/blog/page/22/index.html b/blog/page/22/index.html index 4ad9bfc0e0..2608b8d1ac 100644 --- a/blog/page/22/index.html +++ b/blog/page/22/index.html @@ -10,8 +10,8 @@ - - + +

Stability & Infrastructure Upgrades

· One min read
Aditya Vaidyam
Division of Digital Psychiatry

Improvements

diff --git a/blog/page/3/index.html b/blog/page/3/index.html index bc8a7e6d7a..00214f56ee 100644 --- a/blog/page/3/index.html +++ b/blog/page/3/index.html @@ -10,8 +10,8 @@ - - + +

· One min read
Ashley Meyer
Division of Digital Psychiatry

Features & Improvements

diff --git a/blog/page/4/index.html b/blog/page/4/index.html index 211a06d20e..fa6ddc7dd1 100644 --- a/blog/page/4/index.html +++ b/blog/page/4/index.html @@ -10,8 +10,8 @@ - - + +

· 2 min read
Ashley Meyer
Division of Digital Psychiatry

Features & Improvements

diff --git a/blog/page/5/index.html b/blog/page/5/index.html index 93dfd702a3..379d8a4a4a 100644 --- a/blog/page/5/index.html +++ b/blog/page/5/index.html @@ -10,8 +10,8 @@ - - + +

2022 User Interface Improvements

· One min read
Ashley Meyer
Division of Digital Psychiatry
danger

Server administrators MUST upgrade from :2021 to :2022 versions in the Docker configuration. Please contact us on the forum if there are any questions.

diff --git a/blog/page/6/index.html b/blog/page/6/index.html index 7019be5294..0032c1663f 100644 --- a/blog/page/6/index.html +++ b/blog/page/6/index.html @@ -10,8 +10,8 @@ - - + +

New features, stability fixes, and improvements

· 2 min read
Suraj Patel
Division of Digital Psychiatry

New Features

diff --git a/blog/page/7/index.html b/blog/page/7/index.html index 0344a39819..bfcdb69b40 100644 --- a/blog/page/7/index.html +++ b/blog/page/7/index.html @@ -10,8 +10,8 @@ - - + +

New, fully functional Clinical-specific use for mindLAMP!

· 2 min read
Suraj Patel
Division of Digital Psychiatry

mindLAMP now features a variety of new features to support a clinical-only team if there is no need for specialized researcher functions or if a simpler and streamlined UI is preferred. See our documentation here for greater details.

diff --git a/blog/page/8/index.html b/blog/page/8/index.html index 66cdbdeb03..35d32915e9 100644 --- a/blog/page/8/index.html +++ b/blog/page/8/index.html @@ -10,8 +10,8 @@ - - + +

Scheduled Routine mindLAMP AWS Maintenance

· One min read
Suraj Patel
Division of Digital Psychiatry

Hi all,

diff --git a/blog/page/9/index.html b/blog/page/9/index.html index b209696aca..752955d861 100644 --- a/blog/page/9/index.html +++ b/blog/page/9/index.html @@ -10,8 +10,8 @@ - - + +

Visualization & Activity Updates

· One min read
Suraj Patel
Division of Digital Psychiatry

Updates

diff --git a/bug/index.html b/bug/index.html index 5a1b4d8b61..b5870abbf6 100644 --- a/bug/index.html +++ b/bug/index.html @@ -10,11 +10,11 @@ - - + + +

If you encounter any issues with the app, please check out our community forum: https://mindlamp.discourse.group/

\ No newline at end of file diff --git a/consortium/LAC/Clients/add_note/index.html b/consortium/LAC/Clients/add_note/index.html index e42c9a27c7..3b0adcb35b 100644 --- a/consortium/LAC/Clients/add_note/index.html +++ b/consortium/LAC/Clients/add_note/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/LAC/Clients/download/index.html b/consortium/LAC/Clients/download/index.html index 7ad37e2172..22e830b804 100644 --- a/consortium/LAC/Clients/download/index.html +++ b/consortium/LAC/Clients/download/index.html @@ -10,8 +10,8 @@ - - + + +

The Division of Digital Psychiatry continuously maintains the mindLAMP app for app store regulatory compliance through frequent updates and correspondence with Apple and Google.

\ No newline at end of file diff --git a/consortium/LAC/Clients/emotions/index.html b/consortium/LAC/Clients/emotions/index.html index a6001dc6a4..fb84bca359 100644 --- a/consortium/LAC/Clients/emotions/index.html +++ b/consortium/LAC/Clients/emotions/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/LAC/Clients/find_dbt/index.html b/consortium/LAC/Clients/find_dbt/index.html index bcaefd7d99..b9670f2c81 100644 --- a/consortium/LAC/Clients/find_dbt/index.html +++ b/consortium/LAC/Clients/find_dbt/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/LAC/Clients/login/index.html b/consortium/LAC/Clients/login/index.html index 9b0255adf0..ca0a9e2521 100644 --- a/consortium/LAC/Clients/login/index.html +++ b/consortium/LAC/Clients/login/index.html @@ -10,8 +10,8 @@ - - + + +

If no domain was specified by your IT systems administrator, you can leave that field blank ("lamp.my_organization.org" is only for this example).

\ No newline at end of file diff --git a/consortium/LAC/Clients/skills/index.html b/consortium/LAC/Clients/skills/index.html index ce61aee549..5b50fc001d 100644 --- a/consortium/LAC/Clients/skills/index.html +++ b/consortium/LAC/Clients/skills/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/LAC/Clients/targets/index.html b/consortium/LAC/Clients/targets/index.html index 7eb1fd7d75..d018778d5e 100644 --- a/consortium/LAC/Clients/targets/index.html +++ b/consortium/LAC/Clients/targets/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/LAC/Clinicians/behaviors/index.html b/consortium/LAC/Clinicians/behaviors/index.html index 235037f2dd..c31df0e905 100644 --- a/consortium/LAC/Clinicians/behaviors/index.html +++ b/consortium/LAC/Clinicians/behaviors/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/LAC/Clinicians/create_dbt/index.html b/consortium/LAC/Clinicians/create_dbt/index.html index c13cb31d57..024cdc0188 100644 --- a/consortium/LAC/Clinicians/create_dbt/index.html +++ b/consortium/LAC/Clinicians/create_dbt/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/LAC/Clinicians/customize/index.html b/consortium/LAC/Clinicians/customize/index.html index d4b7be3ffe..c6334e37ed 100644 --- a/consortium/LAC/Clinicians/customize/index.html +++ b/consortium/LAC/Clinicians/customize/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/LAC/Clinicians/delete_user/index.html b/consortium/LAC/Clinicians/delete_user/index.html index a3ca6a5af0..96837124b4 100644 --- a/consortium/LAC/Clinicians/delete_user/index.html +++ b/consortium/LAC/Clinicians/delete_user/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/LAC/Clinicians/emotions/index.html b/consortium/LAC/Clinicians/emotions/index.html index a5210514c8..6b4c15db68 100644 --- a/consortium/LAC/Clinicians/emotions/index.html +++ b/consortium/LAC/Clinicians/emotions/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/LAC/Clinicians/impersonate/index.html b/consortium/LAC/Clinicians/impersonate/index.html index ce4c3bbecb..b554e1521c 100644 --- a/consortium/LAC/Clinicians/impersonate/index.html +++ b/consortium/LAC/Clinicians/impersonate/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/LAC/Clinicians/login/index.html b/consortium/LAC/Clinicians/login/index.html index 0e915cd726..859989c821 100644 --- a/consortium/LAC/Clinicians/login/index.html +++ b/consortium/LAC/Clinicians/login/index.html @@ -10,8 +10,8 @@ - - + + +

If no domain was specified by your IT systems administrator, you can leave that field blank ("lamp.my_organization.org" is only for this example).

\ No newline at end of file diff --git a/consortium/LAC/Clinicians/new_user/index.html b/consortium/LAC/Clinicians/new_user/index.html index 16027ab4da..ac2e61ac63 100644 --- a/consortium/LAC/Clinicians/new_user/index.html +++ b/consortium/LAC/Clinicians/new_user/index.html @@ -10,8 +10,8 @@ - - + + +

Though it appears that the patient has been “renamed,” this new alias is only visible to you, as a clinician or researcher, and not to the user, or anywhere in the data when saved or exported.

\ No newline at end of file diff --git a/consortium/LAC/Clinicians/reset_user/index.html b/consortium/LAC/Clinicians/reset_user/index.html index deb120f0ca..d220bf8a4b 100644 --- a/consortium/LAC/Clinicians/reset_user/index.html +++ b/consortium/LAC/Clinicians/reset_user/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/LAC/Clinicians/user_cred/index.html b/consortium/LAC/Clinicians/user_cred/index.html index 3f0ceb5955..acf60a9a49 100644 --- a/consortium/LAC/Clinicians/user_cred/index.html +++ b/consortium/LAC/Clinicians/user_cred/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/admin/checklist/index.html b/consortium/admin/checklist/index.html index 2952b97ac3..a71f009f74 100644 --- a/consortium/admin/checklist/index.html +++ b/consortium/admin/checklist/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/admin/create_assess_activity/index.html b/consortium/admin/create_assess_activity/index.html index 432b49e3a2..1d92c1f27b 100644 --- a/consortium/admin/create_assess_activity/index.html +++ b/consortium/admin/create_assess_activity/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/admin/create_clinician/index.html b/consortium/admin/create_clinician/index.html index 31b68b7346..6b774634fd 100644 --- a/consortium/admin/create_clinician/index.html +++ b/consortium/admin/create_clinician/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/admin/create_dbt_diary/index.html b/consortium/admin/create_dbt_diary/index.html index 6ab1202739..6a7376dfaf 100644 --- a/consortium/admin/create_dbt_diary/index.html +++ b/consortium/admin/create_dbt_diary/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/admin/create_manage_activity/index.html b/consortium/admin/create_manage_activity/index.html index 81468b2da5..e3f62ee3c1 100644 --- a/consortium/admin/create_manage_activity/index.html +++ b/consortium/admin/create_manage_activity/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/admin/create_study/index.html b/consortium/admin/create_study/index.html index 9975e44759..671dbf188d 100644 --- a/consortium/admin/create_study/index.html +++ b/consortium/admin/create_study/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/admin/create_survey/index.html b/consortium/admin/create_survey/index.html index ba3fc97509..f88c12e926 100644 --- a/consortium/admin/create_survey/index.html +++ b/consortium/admin/create_survey/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/admin/create_tip/index.html b/consortium/admin/create_tip/index.html index 81ac359ca9..90c99f7bd1 100644 --- a/consortium/admin/create_tip/index.html +++ b/consortium/admin/create_tip/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/admin/create_user/index.html b/consortium/admin/create_user/index.html index fd3db21184..7b016dce45 100644 --- a/consortium/admin/create_user/index.html +++ b/consortium/admin/create_user/index.html @@ -10,8 +10,8 @@ - - + + +

Though it appears that the patient has been “renamed,” this new alias is only visible to you, as a clinician or researcher, and not to the user, or anywhere in the data when saved or exported.

\ No newline at end of file diff --git a/consortium/admin/delete_user/index.html b/consortium/admin/delete_user/index.html index 7fa8d6360d..f461b8072b 100644 --- a/consortium/admin/delete_user/index.html +++ b/consortium/admin/delete_user/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/admin/download/index.html b/consortium/admin/download/index.html index 6262b80bd0..c9a6ccc458 100644 --- a/consortium/admin/download/index.html +++ b/consortium/admin/download/index.html @@ -10,8 +10,8 @@ - - + + +

The Division of Digital Psychiatry continuously maintains the mindLAMP app for app store regulatory compliance through frequent updates and correspondence with Apple and Google.

\ No newline at end of file diff --git a/consortium/admin/login/index.html b/consortium/admin/login/index.html index f67648da7b..7b4003d6b6 100644 --- a/consortium/admin/login/index.html +++ b/consortium/admin/login/index.html @@ -10,8 +10,8 @@ - - + + +

If no domain was specified by your IT systems administrator, you can leave that field blank ("lamp.my_organization.org" is only for this example).

\ No newline at end of file diff --git a/consortium/admin/reset_clinician/index.html b/consortium/admin/reset_clinician/index.html index 61011c4dae..615711cc47 100644 --- a/consortium/admin/reset_clinician/index.html +++ b/consortium/admin/reset_clinician/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/admin/reset_user/index.html b/consortium/admin/reset_user/index.html index d18c7d0b3f..f743dc5845 100644 --- a/consortium/admin/reset_user/index.html +++ b/consortium/admin/reset_user/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/admin/sched_delete-activity/index.html b/consortium/admin/sched_delete-activity/index.html index 85f53c455a..37c04d086f 100644 --- a/consortium/admin/sched_delete-activity/index.html +++ b/consortium/admin/sched_delete-activity/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/joining/guidelines/index.html b/consortium/joining/guidelines/index.html index de3aa8d7f9..e9f83f2f0e 100644 --- a/consortium/joining/guidelines/index.html +++ b/consortium/joining/guidelines/index.html @@ -10,11 +10,11 @@ - - + + +

To learn more about guidelines for mindLAMP use, contact Dr. John Torous at jtorous@bidmc.harvard.edu

\ No newline at end of file diff --git a/consortium/joining/intro/index.html b/consortium/joining/intro/index.html index 5f11b43ead..18b79154bc 100644 --- a/consortium/joining/intro/index.html +++ b/consortium/joining/intro/index.html @@ -10,8 +10,8 @@ - - + +

Introduction

@@ -23,6 +23,6 @@

Consortium Partner

Your team can utilize mindLAMP as it is built today with support from us. We will also include you in monthly webinars. As a partner, you are a member of the LAMP Consortium – a community of LAMP users who share research and ideas.

Consortium partners are required to host their own data if they are not part of Beth Israel Deaconess Medical Center.

-

If your team is interested in building additional functions and features on LAMP – whether you are a Self-Deploying User or Consortium Partner – you can provide us with a detailed understanding of the functions and features and we will work with our engineering and design partners to determine the feasibility, cost, and a realistic timeline.

+

If your team is interested in building additional functions and features on LAMP – whether you are a Self-Deploying User or Consortium Partner – you can provide us with a detailed understanding of the functions and features and we will work with our engineering and design partners to determine the feasibility, cost, and a realistic timeline.

\ No newline at end of file diff --git a/consortium/joining/register/index.html b/consortium/joining/register/index.html index 7b1a0b691d..c04be9ebad 100644 --- a/consortium/joining/register/index.html +++ b/consortium/joining/register/index.html @@ -10,14 +10,14 @@ - - + + +
\ No newline at end of file diff --git a/consortium/joining/requirements/index.html b/consortium/joining/requirements/index.html index f7683756f2..676b4590b5 100644 --- a/consortium/joining/requirements/index.html +++ b/consortium/joining/requirements/index.html @@ -10,11 +10,11 @@ - - + + +

To learn more about guidelines for mindLAMP use, contact Dr. John Torous at jtorous@bidmc.harvard.edu

\ No newline at end of file diff --git a/consortium/joining/webinars/index.html b/consortium/joining/webinars/index.html index 50058c2780..c8d989368d 100644 --- a/consortium/joining/webinars/index.html +++ b/consortium/joining/webinars/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/mapnet/index.html b/consortium/mapnet/index.html index a9f1c6b12a..6cd0158238 100644 --- a/consortium/mapnet/index.html +++ b/consortium/mapnet/index.html @@ -10,8 +10,8 @@ - - + + +
NameStatusSubmitted by
Include Activity Names in CSV ExportSubmittedAlyssa Williamson, Molly Stettenbauer
Specify between baseline and follow up assessmentsSubmittedAlyssa Williamson
Ability to export all patients from all clinics to csv from the dashboardSubmittedAlyssa Williamson
Add ability to change the date field from the dashboard retroactivelySubmittedAlyssa Williamson
Change data responses to be numerical valuesSubmittedMolly Stettenbauer
Self report versus clinician administered scales being available to only patients versus only cliniciansSubmitted
Being able to save clinical notes somewhere while doing clinician administered surveys for patientsSubmitted
Reverse coding survey questionsSubmitted
Specifically marking questions is required versus optionalSubmittedEmily He
Add a BMI auto calculator to it so when you plug in weight and height it fills in the BMISubmitted
Conditional LogicSubmitted
Editing Survey QuestionsSubmittedAlyssa Williamson
Sum scores from the MOASSubmittedMolly Stettenbauer
Hide prevent graphs from patientsCompleted
\ No newline at end of file diff --git a/consortium/patient/checklist/index.html b/consortium/patient/checklist/index.html index c6d99577a6..0456644c73 100644 --- a/consortium/patient/checklist/index.html +++ b/consortium/patient/checklist/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/patient/complete_activities/index.html b/consortium/patient/complete_activities/index.html index 5ec07cb10a..7556798be2 100644 --- a/consortium/patient/complete_activities/index.html +++ b/consortium/patient/complete_activities/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/patient/download/index.html b/consortium/patient/download/index.html index e8ef1d3aa6..09bca1c160 100644 --- a/consortium/patient/download/index.html +++ b/consortium/patient/download/index.html @@ -10,8 +10,8 @@ - - + + +

The Division of Digital Psychiatry continuously maintains the mindLAMP app for app store regulatory compliance through frequent updates and correspondence with Apple and Google.

\ No newline at end of file diff --git a/consortium/patient/login/index.html b/consortium/patient/login/index.html index 958453e91c..ce9f1ccd6b 100644 --- a/consortium/patient/login/index.html +++ b/consortium/patient/login/index.html @@ -10,8 +10,8 @@ - - + + +

If no domain was specified by your IT systems administrator, you can leave that field blank ("lamp.my_organization.org" is only for this example).

\ No newline at end of file diff --git a/consortium/patient/read_tip/index.html b/consortium/patient/read_tip/index.html index cec32ad060..86211ff517 100644 --- a/consortium/patient/read_tip/index.html +++ b/consortium/patient/read_tip/index.html @@ -10,10 +10,10 @@ - - + + - + \ No newline at end of file diff --git a/consortium/researcher/DBT/create_dbt_diary/index.html b/consortium/researcher/DBT/create_dbt_diary/index.html index 858394f5c6..f6ea00c5c9 100644 --- a/consortium/researcher/DBT/create_dbt_diary/index.html +++ b/consortium/researcher/DBT/create_dbt_diary/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/researcher/checklist/index.html b/consortium/researcher/checklist/index.html index 1ca1d5f41f..9a78e85d02 100644 --- a/consortium/researcher/checklist/index.html +++ b/consortium/researcher/checklist/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/researcher/create_assess_activity/index.html b/consortium/researcher/create_assess_activity/index.html index 70294cb9c6..23d78929bb 100644 --- a/consortium/researcher/create_assess_activity/index.html +++ b/consortium/researcher/create_assess_activity/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/researcher/create_dbt/index.html b/consortium/researcher/create_dbt/index.html index edf851a802..01b20baf93 100644 --- a/consortium/researcher/create_dbt/index.html +++ b/consortium/researcher/create_dbt/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/researcher/create_manage_activity/index.html b/consortium/researcher/create_manage_activity/index.html index 679ca4b336..bd35402d4e 100644 --- a/consortium/researcher/create_manage_activity/index.html +++ b/consortium/researcher/create_manage_activity/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/researcher/create_study/index.html b/consortium/researcher/create_study/index.html index 736af93f92..81c3123d05 100644 --- a/consortium/researcher/create_study/index.html +++ b/consortium/researcher/create_study/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/consortium/researcher/create_survey/index.html b/consortium/researcher/create_survey/index.html index 5ac5043853..001d80fa52 100644 --- a/consortium/researcher/create_survey/index.html +++ b/consortium/researcher/create_survey/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/researcher/create_tip/index.html b/consortium/researcher/create_tip/index.html index d0177db5dc..cedf8c3608 100644 --- a/consortium/researcher/create_tip/index.html +++ b/consortium/researcher/create_tip/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/researcher/create_user/index.html b/consortium/researcher/create_user/index.html index 07da4b6a9f..a853e038cf 100644 --- a/consortium/researcher/create_user/index.html +++ b/consortium/researcher/create_user/index.html @@ -10,8 +10,8 @@ - - + + +

Though it appears that the patient has been “renamed,” this new alias is only visible to you, as a clinician or researcher, and not to the user, or anywhere in the data when saved or exported.

\ No newline at end of file diff --git a/consortium/researcher/delete_user/index.html b/consortium/researcher/delete_user/index.html index 0d1c3cc2d2..8d5b097e86 100644 --- a/consortium/researcher/delete_user/index.html +++ b/consortium/researcher/delete_user/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/researcher/download/index.html b/consortium/researcher/download/index.html index df83c2ae98..2a4e316424 100644 --- a/consortium/researcher/download/index.html +++ b/consortium/researcher/download/index.html @@ -10,8 +10,8 @@ - - + + +

The Division of Digital Psychiatry continuously maintains the mindLAMP app for app store regulatory compliance through frequent updates and correspondence with Apple and Google.

\ No newline at end of file diff --git a/consortium/researcher/login/index.html b/consortium/researcher/login/index.html index 273ead190e..9dbfbae573 100644 --- a/consortium/researcher/login/index.html +++ b/consortium/researcher/login/index.html @@ -10,8 +10,8 @@ - - + + +

If no domain was specified by your IT systems administrator, you can leave that field blank ("lamp.my_organization.org" is only for this example).

\ No newline at end of file diff --git a/consortium/researcher/reset_user/index.html b/consortium/researcher/reset_user/index.html index 85fc11e745..8d48987642 100644 --- a/consortium/researcher/reset_user/index.html +++ b/consortium/researcher/reset_user/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/consortium/researcher/sched_delete-activity/index.html b/consortium/researcher/sched_delete-activity/index.html index 697640a64d..ab2ab59179 100644 --- a/consortium/researcher/sched_delete-activity/index.html +++ b/consortium/researcher/sched_delete-activity/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/data_science/cortex/advanced/index.html b/data_science/cortex/advanced/index.html index 6ccd0a8835..eaaf2650f1 100644 --- a/data_science/cortex/advanced/index.html +++ b/data_science/cortex/advanced/index.html @@ -10,8 +10,8 @@ - - + +

Advanced Usage

@@ -44,6 +44,6 @@

Configuration<

Or another example using the CLI arguments instead of environment variables (and outputting to a file):

python3 -m \
cortex --format=csv --server-address=api.lamp.digital --access-key=XXX --secret-key=XXX \
survey --id=U26468383 --start=1583532346000 --end=1583618746000 \
2>/dev/null 1>./my_cortex_output.csv

Example

-
# environment variables must already contain LAMP configuration info
from pprint import pprint
from cortex import all_features, significant_locations, trips
pprint(all_features())
for i in range(1583532346000, 1585363115000, 86400000):
pprint(significant_locations(id="U26468383", start=i, end=i + 86400000))
+
# environment variables must already contain LAMP configuration info
from pprint import pprint
from cortex import all_features, significant_locations, trips
pprint(all_features())
for i in range(1583532346000, 1585363115000, 86400000):
pprint(significant_locations(id="U26468383", start=i, end=i + 86400000))
\ No newline at end of file diff --git a/data_science/cortex/developing_cortex/index.html b/data_science/cortex/developing_cortex/index.html index 4e9dd3ae68..c17e76613d 100644 --- a/data_science/cortex/developing_cortex/index.html +++ b/data_science/cortex/developing_cortex/index.html @@ -10,8 +10,8 @@ - - + +
+
\ No newline at end of file diff --git a/data_science/cortex/features/primary/acc_jerk/index.html b/data_science/cortex/features/primary/acc_jerk/index.html index 8478b5853f..75a647e473 100644 --- a/data_science/cortex/features/primary/acc_jerk/index.html +++ b/data_science/cortex/features/primary/acc_jerk/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 1627067480000,
'data': [
{'timestamp': 1607094903526, 'acc_jerk': 0.008896610358911157},
.
.
.
{'timestamp': 1607094950000, 'acc_jerk': 0.0028039384631051243}
],
'has_raw_data': 1,
}
\ No newline at end of file diff --git a/data_science/cortex/features/primary/deprecated_features/sleep_periods/index.html b/data_science/cortex/features/primary/deprecated_features/sleep_periods/index.html index e07ff97cd2..409348f50b 100644 --- a/data_science/cortex/features/primary/deprecated_features/sleep_periods/index.html +++ b/data_science/cortex/features/primary/deprecated_features/sleep_periods/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 5616000000,
'data': [
{'start': 1607116800000, 'end': 1607146800000},
{'start': 1607205600000, 'end': 1607233800000},
.
.
.
{'start': 1607980200000, 'end': 1608009600000}
],
'has_raw_data': 1,
}
\ No newline at end of file diff --git a/data_science/cortex/features/primary/game_level_scores/index.html b/data_science/cortex/features/primary/game_level_scores/index.html index 5ddbf83c74..051451872a 100644 --- a/data_science/cortex/features/primary/game_level_scores/index.html +++ b/data_science/cortex/features/primary/game_level_scores/index.html @@ -10,8 +10,8 @@ - - + +

Game level scores

@@ -44,6 +44,6 @@

DataExample

cortex.primary.game_level_scores.game_level_scores(id="U1234567890", start=0, end=cortex.now(), name_of_game="jewels_b")

Output:

-
{
'timestamp': 0,
'duration': 1627067480000,
'data': [
{'start': 1639759199227, 'end': 1639777579969, 'level': 1, 'avg_tap_time': 1233.5, 'jewels_collected': 25, 'perc_correct': 0.995},
{'start': 1639759199227, 'end': 1639777579969, 'level': 1, 'avg_tap_time': 1009.2, 'jewels_collected': 25, 'perc_correct': 1.0},
.
.
.
{'start': 1639426388269, 'end': 1639426610663, 'level': 3, 'avg_tap_time': 981.24, 'jewels_collected': 21, 'perc_correct': 1.0},
],
'has_raw_data': 1,
}
+
{
'timestamp': 0,
'duration': 1627067480000,
'data': [
{'start': 1639759199227, 'end': 1639777579969, 'level': 1, 'avg_tap_time': 1233.5, 'jewels_collected': 25, 'perc_correct': 0.995},
{'start': 1639759199227, 'end': 1639777579969, 'level': 1, 'avg_tap_time': 1009.2, 'jewels_collected': 25, 'perc_correct': 1.0},
.
.
.
{'start': 1639426388269, 'end': 1639426610663, 'level': 3, 'avg_tap_time': 981.24, 'jewels_collected': 21, 'perc_correct': 1.0},
],
'has_raw_data': 1,
}
\ No newline at end of file diff --git a/data_science/cortex/features/primary/overview/index.html b/data_science/cortex/features/primary/overview/index.html index c255a5a4f7..4ec4c02655 100644 --- a/data_science/cortex/features/primary/overview/index.html +++ b/data_science/cortex/features/primary/overview/index.html @@ -10,8 +10,8 @@ - - + +

Primary Feature Overview

@@ -25,6 +25,6 @@

'has_raw_d

If there is no device_state data, screen_active will return the following:

{
'timestamp': 1607072400000,
'duration': 5616000000,
'data': [
],
'has_raw_data': 0,
}

However, if there is device_state data, but only "screen_off" events (so there are no bouts where the screen is "on") the following will be returned:

-
{
'timestamp': 1607072400000,
'duration': 5616000000,
'data': [
],
'has_raw_data': 1,
}

+
{
'timestamp': 1607072400000,
'duration': 5616000000,
'data': [
],
'has_raw_data': 1,
}
\ No newline at end of file diff --git a/data_science/cortex/features/primary/screen_active/index.html b/data_science/cortex/features/primary/screen_active/index.html index 426a58f4c8..7bc1a181b2 100644 --- a/data_science/cortex/features/primary/screen_active/index.html +++ b/data_science/cortex/features/primary/screen_active/index.html @@ -10,8 +10,8 @@ - - + +

Screen Active

@@ -39,6 +39,6 @@

DataExample

cortex.primary.screen_active.screen_active(id="U1234567890", start=1607072400000, end=cortex.now())

Output:

-
{
'timestamp': 1607072400000,
'duration': 5616000000,
'data': [
{'start': 1607094896733, 'end': 1607100072241, 'duration': 5175508},
{'start': 1607100076065, 'end': 1607100088981, 'duration': 12916},
.
.
.
{'start': 1607103351139, 'end': 1607108478253, 'duration': 5127114}
],
'has_raw_data': 1,
}
+
{
'timestamp': 1607072400000,
'duration': 5616000000,
'data': [
{'start': 1607094896733, 'end': 1607100072241, 'duration': 5175508},
{'start': 1607100076065, 'end': 1607100088981, 'duration': 12916},
.
.
.
{'start': 1607103351139, 'end': 1607108478253, 'duration': 5127114}
],
'has_raw_data': 1,
}
\ No newline at end of file diff --git a/data_science/cortex/features/primary/sig_locs/index.html b/data_science/cortex/features/primary/sig_locs/index.html index 7cfe837950..32ee0fb0d4 100644 --- a/data_science/cortex/features/primary/sig_locs/index.html +++ b/data_science/cortex/features/primary/sig_locs/index.html @@ -10,8 +10,8 @@ - - + +

Significant Locations

@@ -53,6 +53,6 @@

Example 1 - using method='mode' with max_clusters set to 2

cortex.primary.significant_locations.significant_locations(id="U1234567890",
start=1607072400000,
end=cortex.now(),
max_clusters=2,
min_cluster_size=0.01)

Output:

-
{
'timestamp': 1607072400000,
'duration': 5616000000,
'data': [
{
'start': 1607072400000,
'end': 1612688400000,
'latitude': 42.338,
'longitude': -71.084,
'rank': 0,
'radius': 24.29582585958463,
'proportion': 0.7652037614040124,
'duration': 1218884313
},
{
'start': 1607072400000,
'end': 1612688400000,
'latitude': 42.076,
'longitude': -71.255,
'rank': 1,
'radius': 21.562489967625048,
'proportion': 0.23479623859598767,
'duration': 566147289
}
],
'has_raw_data': 1,
}
+
{
'timestamp': 1607072400000,
'duration': 5616000000,
'data': [
{
'start': 1607072400000,
'end': 1612688400000,
'latitude': 42.338,
'longitude': -71.084,
'rank': 0,
'radius': 24.29582585958463,
'proportion': 0.7652037614040124,
'duration': 1218884313
},
{
'start': 1607072400000,
'end': 1612688400000,
'latitude': 42.076,
'longitude': -71.255,
'rank': 1,
'radius': 21.562489967625048,
'proportion': 0.23479623859598767,
'duration': 566147289
}
],
'has_raw_data': 1,
}
\ No newline at end of file diff --git a/data_science/cortex/features/primary/survey_scores/index.html b/data_science/cortex/features/primary/survey_scores/index.html index 9eab5313bb..893a241898 100644 --- a/data_science/cortex/features/primary/survey_scores/index.html +++ b/data_science/cortex/features/primary/survey_scores/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/data_science/cortex/features/primary/trips/index.html b/data_science/cortex/features/primary/trips/index.html index bf9942983d..9ac1704795 100644 --- a/data_science/cortex/features/primary/trips/index.html +++ b/data_science/cortex/features/primary/trips/index.html @@ -10,8 +10,8 @@ - - + +

Trips

@@ -34,6 +34,6 @@

DataExample

cortex.primary.trips.trips(id="U1234567890", start=0, end=cortex.now())

Output:

-
{
'timestamp': 0,
'duration': 1627067480000,
'data': [
{'start': 1607094903526, 'end': 1607094905476, 'latitude': 42.33786999329302, 'longitude': -71.0842230494398, 'distance': 0.008896610358911157},
{'start': 1607094907376, 'end': 1607094933999, 'latitude': 42.33787296688118, 'longitude': -71.08414299583944, 'distance': 0.015118418131814458},
.
.
.
{'start': 1607094950000, 'end': 1607094950000, 'latitude': 42.3379491204939, 'longitude': -71.08427063527692, 'distance': 0.0028039384631051243}
],
'has_raw_data': 1,
}
+
{
'timestamp': 0,
'duration': 1627067480000,
'data': [
{'start': 1607094903526, 'end': 1607094905476, 'latitude': 42.33786999329302, 'longitude': -71.0842230494398, 'distance': 0.008896610358911157},
{'start': 1607094907376, 'end': 1607094933999, 'latitude': 42.33787296688118, 'longitude': -71.08414299583944, 'distance': 0.015118418131814458},
.
.
.
{'start': 1607094950000, 'end': 1607094950000, 'latitude': 42.3379491204939, 'longitude': -71.08427063527692, 'distance': 0.0028039384631051243}
],
'has_raw_data': 1,
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/call_degree/index.html b/data_science/cortex/features/secondary/call_degree/index.html index efe43129b7..3d4d0b40a3 100644 --- a/data_science/cortex/features/secondary/call_degree/index.html +++ b/data_science/cortex/features/secondary/call_degree/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 0},
{'timestamp': 1607331600000, 'value': 2},
.
.
.
{'timestamp': 1609232400000, 'value': 4}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/call_duration/index.html b/data_science/cortex/features/secondary/call_duration/index.html index 16dc077c10..4672ebad39 100644 --- a/data_science/cortex/features/secondary/call_duration/index.html +++ b/data_science/cortex/features/secondary/call_duration/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 111},
{'timestamp': 1607331600000, 'value': 0},
.
.
.
{'timestamp': 1609232400000, 'value': 7}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/call_number/index.html b/data_science/cortex/features/secondary/call_number/index.html index 7c1714e3de..76b2561fe1 100644 --- a/data_science/cortex/features/secondary/call_number/index.html +++ b/data_science/cortex/features/secondary/call_number/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 0},
{'timestamp': 1607331600000, 'value': 6},
.
.
.
{'timestamp': 1609232400000, 'value': 3}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/data_quality/index.html b/data_science/cortex/features/secondary/data_quality/index.html index a491d6e53f..0f8ac9b42c 100644 --- a/data_science/cortex/features/secondary/data_quality/index.html +++ b/data_science/cortex/features/secondary/data_quality/index.html @@ -10,8 +10,8 @@ - - + +

Data Quality

@@ -36,6 +36,6 @@

DataExample

cortex.secondary.data_quality.data_quality(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000, feature="gps", bin_size=10000)

Output:

-
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 1.0},
{'timestamp': 1607331600000, 'value': 0.789291823},
.
.
.
{'timestamp': 1609232400000, 'value': 0.121212344}
]
}
+
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 1.0},
{'timestamp': 1607331600000, 'value': 0.789291823},
.
.
.
{'timestamp': 1609232400000, 'value': 0.121212344}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count/index.html b/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count/index.html index e3bbbc3985..c033a26a1f 100644 --- a/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count/index.html +++ b/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count/index.html @@ -10,8 +10,8 @@ - - + +
+
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 0},
{'timestamp': 1607331600000, 'value': 6},
.
.
.
{'timestamp': 1609232400000, 'value': 3}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/deprecated_features/sleep_duration/index.html b/data_science/cortex/features/secondary/deprecated_features/sleep_duration/index.html index bb36b9e287..10637600b0 100644 --- a/data_science/cortex/features/secondary/deprecated_features/sleep_duration/index.html +++ b/data_science/cortex/features/secondary/deprecated_features/sleep_duration/index.html @@ -10,8 +10,8 @@ - - + +
+
{
'timestamp': 0,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 38720178},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 12218716}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/deprecated_features/sms_number/index.html b/data_science/cortex/features/secondary/deprecated_features/sms_number/index.html index ff519b259f..65505dd736 100644 --- a/data_science/cortex/features/secondary/deprecated_features/sms_number/index.html +++ b/data_science/cortex/features/secondary/deprecated_features/sms_number/index.html @@ -10,8 +10,8 @@ - - + +
+
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 0},
{'timestamp': 1607331600000, 'value': 0},
.
.
.
{'timestamp': 1609232400000, 'value': 3}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/entropy/index.html b/data_science/cortex/features/secondary/entropy/index.html index 86ad267ecf..01077ab82b 100644 --- a/data_science/cortex/features/secondary/entropy/index.html +++ b/data_science/cortex/features/secondary/entropy/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 0.16071499652789484},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 0.8753883626144159}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/game_results/index.html b/data_science/cortex/features/secondary/game_results/index.html index d46c66d028..9a5b492317 100644 --- a/data_science/cortex/features/secondary/game_results/index.html +++ b/data_science/cortex/features/secondary/game_results/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 4524000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 1002.2},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 1527.82}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/healthkit_sleep_duration/index.html b/data_science/cortex/features/secondary/healthkit_sleep_duration/index.html index 94ade31463..25d348c0d2 100644 --- a/data_science/cortex/features/secondary/healthkit_sleep_duration/index.html +++ b/data_science/cortex/features/secondary/healthkit_sleep_duration/index.html @@ -10,8 +10,8 @@ - - + +

Healthkit Sleep Duration

@@ -33,6 +33,6 @@

DataExample

cortex.secondary.healthkit_sleep_duration.healthkit_sleep_duration(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000, duration_type="in_bed")

Output:

-
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': None},
{'timestamp': 1607331600000, 'value': 20000027},
.
.
.
{'timestamp': 1609232400000, 'value': 30040029}
]
}
+
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': None},
{'timestamp': 1607331600000, 'value': 20000027},
.
.
.
{'timestamp': 1609232400000, 'value': 30040029}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/hometime/index.html b/data_science/cortex/features/secondary/hometime/index.html index d8948d8891..18d98cad6d 100644 --- a/data_science/cortex/features/secondary/hometime/index.html +++ b/data_science/cortex/features/secondary/hometime/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 44145818},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 2188582}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/inactive_duration/index.html b/data_science/cortex/features/secondary/inactive_duration/index.html index 8454001901..04fef50b69 100644 --- a/data_science/cortex/features/secondary/inactive_duration/index.html +++ b/data_science/cortex/features/secondary/inactive_duration/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 38720178},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 12218716}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/nearby_device_count/index.html b/data_science/cortex/features/secondary/nearby_device_count/index.html index b0e530fa6f..17b436d3bb 100644 --- a/data_science/cortex/features/secondary/nearby_device_count/index.html +++ b/data_science/cortex/features/secondary/nearby_device_count/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 1646485947205,
'duration': 517846633,
'resolution': 86400000,
'data': [
{'timestamp': 1646485947205, 'value': 3},
{'timestamp': 1646572347205, 'value': None},
.
.
.
{'timestamp': 1646831547205, 'value': None}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/overview/index.html b/data_science/cortex/features/secondary/overview/index.html index 9db4fb36c1..ff9ac1f69a 100644 --- a/data_science/cortex/features/secondary/overview/index.html +++ b/data_science/cortex/features/secondary/overview/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/screen_duration/index.html b/data_science/cortex/features/secondary/screen_duration/index.html index a08038836f..ad3629bc3a 100644 --- a/data_science/cortex/features/secondary/screen_duration/index.html +++ b/data_science/cortex/features/secondary/screen_duration/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 63720178},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 86218716}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/step_count/index.html b/data_science/cortex/features/secondary/step_count/index.html index f97184250a..42b6072d5c 100644 --- a/data_science/cortex/features/secondary/step_count/index.html +++ b/data_science/cortex/features/secondary/step_count/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 1607072400000,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 0},
{'timestamp': 1607331600000, 'value': 1027},
.
.
.
{'timestamp': 1609232400000, 'value': 13208}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/survey_results/index.html b/data_science/cortex/features/secondary/survey_results/index.html index 46882ab558..3ce541956b 100644 --- a/data_science/cortex/features/secondary/survey_results/index.html +++ b/data_science/cortex/features/secondary/survey_results/index.html @@ -10,8 +10,8 @@ - - + +

Survey Results

@@ -34,6 +34,6 @@

DataExample

scoring_dict = {
"category_list": ["GAD-7"],
"questions": {
"Over the past week, I have felt nervous, anxious, or on edge.": {"category": "GAD-7", "scoring": "value_map"},
"Over the past week, I have not been able to stop or control worrying.": {"category": "GAD-7", "scoring": "value_map"},
"Over the past week, I have been worrying too much about different things.": {"category": "GAD-7", "scoring": "value_map"},
"Over the past week, I have had trouble relaxing.": {"category": "GAD-7", "scoring": "value_map"},
"Over the past week, I have felt so restless that it's hard to sit still.": {"category": "GAD-7", "scoring": "value_map"},
"Over the past week, I have felt myself becoming easily annoyed or irritable.": {"category": "GAD-7", "scoring": "value_map"},
"Over the past week, I have felt afraid as if something awful might happen.": {"category": "GAD-7", "scoring": "value_map"},
},
"value_map": {
"Not at all": 0,
"Several days": 1,
"More than half the days": 2,
"Nearly every day": 3
},
}
cortex.secondary.survey_results.survey_results(id="U1234567890", start=1607072400000, end=1609232400001, resolution=86400000,
scoring_dict=scoring_dict, question_or_category="GAD-7")

Output:

-
{
'timestamp': 0,
'duration': 4524000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 5},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 2.5}
]
}
+
{
'timestamp': 0,
'duration': 4524000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 5},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 2.5}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/trip_distance/index.html b/data_science/cortex/features/secondary/trip_distance/index.html index 6496251046..f94eeb10eb 100644 --- a/data_science/cortex/features/secondary/trip_distance/index.html +++ b/data_science/cortex/features/secondary/trip_distance/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 5616000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 0.018896610358911157},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 0.0228039384631051243}
]
}
\ No newline at end of file diff --git a/data_science/cortex/features/secondary/trip_duration/index.html b/data_science/cortex/features/secondary/trip_duration/index.html index 04227a2da2..b46bf1d7fb 100644 --- a/data_science/cortex/features/secondary/trip_duration/index.html +++ b/data_science/cortex/features/secondary/trip_duration/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 0,
'duration': 4524000000,
'resolution': 86400000,
'data': [
{'timestamp': 1607072400000, 'value': 32720174},
{'timestamp': 1607331600000, 'value': None},
.
.
.
{'timestamp': 1609232400000, 'value': 29213514}
]
}
\ No newline at end of file diff --git a/data_science/cortex/getting-started/index.html b/data_science/cortex/getting-started/index.html index a9b7c576f1..6ecda1da35 100644 --- a/data_science/cortex/getting-started/index.html +++ b/data_science/cortex/getting-started/index.html @@ -10,8 +10,8 @@ - - + +

Cortex Quick Start Guide

@@ -51,6 +51,6 @@

id,timestamp,survey,item,value,type,duration,level
U123456789,2020-01-16 20:57:01,RA,RA Initials,test,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire, I feel better about myself,Neither agree nor disagree,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I feel able to take chances in life,Agree Strongly,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I am able to develop positive relationships with other people ,Agree,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire, I feel part of society rather than isolated,Neither agree nor disagree,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I am able to assert myself,Disagree ,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I feel that my life has a purpose ,Agree Strongly,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,My experiences have changed me for the better,Agree,,0,
U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire, I have been able to come to terms with things that have happened to me in the past and move on with my life,Disagree,,0,

You can then load this CSV file into Microsoft Excel (or Apple Numbers on macOS). Additionally, you can add Categories to group the data by ID, survey, and the specific time that the survey was taken.

-

+

\ No newline at end of file diff --git a/data_science/cortex/running_cortex/index.html b/data_science/cortex/running_cortex/index.html index 4a5703a062..8836606486 100644 --- a/data_science/cortex/running_cortex/index.html +++ b/data_science/cortex/running_cortex/index.html @@ -10,8 +10,8 @@ - - + +

Running Cortex

@@ -38,6 +38,6 @@

DataExample

cortex.run("dhfiej29384",
features=['screen_duration', 'data_quality'],
feature_params={'screen_duration': {}, 'data_quality': {"feature":"gps", "bin_size":3600000}},
start=1638248400000,
end=1638248400000 + 7 * MS_IN_DAY)

Output:

-
{'screen_duration':             id           timestamp       value
0 U7869554142 2021-11-30 05:00:00 25588172.0
1 U7869554142 2021-12-01 05:00:00 15561390.0
2 U7869554142 2021-12-02 05:00:00 25896531.0
3 U7869554142 2021-12-03 05:00:00 33756622.0
4 U7869554142 2021-12-04 05:00:00 16850746.0
5 U7869554142 2021-12-05 05:00:00 19710799.0
0 U1949510612 2021-11-30 05:00:00 0.0
1 U1949510612 2021-12-01 05:00:00 184235.0
2 U1949510612 2021-12-02 05:00:00 0.0
3 U1949510612 2021-12-03 05:00:00 15452842.0
4 U1949510612 2021-12-04 05:00:00 13476068.0
5 U1949510612 2021-12-05 05:00:00 31316368.0,
'data_quality': id timestamp value
0 U7869554142 2021-11-30 05:00:00 0.791667
1 U7869554142 2021-12-01 05:00:00 0.958333
2 U7869554142 2021-12-02 05:00:00 0.916667
3 U7869554142 2021-12-03 05:00:00 1.000000
4 U7869554142 2021-12-04 05:00:00 0.958333
5 U7869554142 2021-12-05 05:00:00 0.708333
0 U1949510612 2021-11-30 05:00:00 0.041667
1 U1949510612 2021-12-01 05:00:00 0.041667
2 U1949510612 2021-12-02 05:00:00 0.000000
3 U1949510612 2021-12-03 05:00:00 0.416667
4 U1949510612 2021-12-04 05:00:00 0.750000
5 U1949510612 2021-12-05 05:00:00 1.000000}
+
{'screen_duration':             id           timestamp       value
0 U7869554142 2021-11-30 05:00:00 25588172.0
1 U7869554142 2021-12-01 05:00:00 15561390.0
2 U7869554142 2021-12-02 05:00:00 25896531.0
3 U7869554142 2021-12-03 05:00:00 33756622.0
4 U7869554142 2021-12-04 05:00:00 16850746.0
5 U7869554142 2021-12-05 05:00:00 19710799.0
0 U1949510612 2021-11-30 05:00:00 0.0
1 U1949510612 2021-12-01 05:00:00 184235.0
2 U1949510612 2021-12-02 05:00:00 0.0
3 U1949510612 2021-12-03 05:00:00 15452842.0
4 U1949510612 2021-12-04 05:00:00 13476068.0
5 U1949510612 2021-12-05 05:00:00 31316368.0,
'data_quality': id timestamp value
0 U7869554142 2021-11-30 05:00:00 0.791667
1 U7869554142 2021-12-01 05:00:00 0.958333
2 U7869554142 2021-12-02 05:00:00 0.916667
3 U7869554142 2021-12-03 05:00:00 1.000000
4 U7869554142 2021-12-04 05:00:00 0.958333
5 U7869554142 2021-12-05 05:00:00 0.708333
0 U1949510612 2021-11-30 05:00:00 0.041667
1 U1949510612 2021-12-01 05:00:00 0.041667
2 U1949510612 2021-12-02 05:00:00 0.000000
3 U1949510612 2021-12-03 05:00:00 0.416667
4 U1949510612 2021-12-04 05:00:00 0.750000
5 U1949510612 2021-12-05 05:00:00 1.000000}
\ No newline at end of file diff --git a/data_science/cortex/utils/activities/index.html b/data_science/cortex/utils/activities/index.html index 6f5c61b50a..f1ce46ab6f 100644 --- a/data_science/cortex/utils/activities/index.html +++ b/data_science/cortex/utils/activities/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/data_science/cortex/utils/database/index.html b/data_science/cortex/utils/database/index.html index f295634957..cb33614b90 100644 --- a/data_science/cortex/utils/database/index.html +++ b/data_science/cortex/utils/database/index.html @@ -10,8 +10,8 @@ - - + +

Database functions

@@ -114,6 +114,6 @@

ArgsExample

import cortex
MONGO_URL = "mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]"
print(LAMP.Study.all_by_researcher('ffmz65mn1gtav5fq3bhq')['data'])
cortex.utils.db.restore_activities_manually('dynp0g0530xkahnzh0xc',client_url=MONGO_URL)

Result

-
[{'id': 'ef0b54h281vfmhc0515d', 'name': 'LAMP Testing (Internal - Luke)'}, {'id': 'dynp0g0530xkahnzh0xc', 'name': 'Second Study'}]

The following activities are deleted
0:Jewels A testing:qa0k8arrv8cx1brp724d
1:Jewels B Testing:4at12eky0manz92bvhbj
2:Test Survey:fgqyjzspc92n2nwb8d7d
3:Scratch Card:8z9vcgewqt1j9vknm48d
Please input, comma-seperated, the numbers of the activity you would like to restore. (e.g. 1,4)
1,3
All done. As of now:
The following activities are deleted
0:Jewels A testing:qa0k8arrv8cx1brp724d
1:Test Survey:fgqyjzspc92n2nwb8d7d
+
[{'id': 'ef0b54h281vfmhc0515d', 'name': 'LAMP Testing (Internal - Luke)'}, {'id': 'dynp0g0530xkahnzh0xc', 'name': 'Second Study'}]

The following activities are deleted
0:Jewels A testing:qa0k8arrv8cx1brp724d
1:Jewels B Testing:4at12eky0manz92bvhbj
2:Test Survey:fgqyjzspc92n2nwb8d7d
3:Scratch Card:8z9vcgewqt1j9vknm48d
Please input, comma-seperated, the numbers of the activity you would like to restore. (e.g. 1,4)
1,3
All done. As of now:
The following activities are deleted
0:Jewels A testing:qa0k8arrv8cx1brp724d
1:Test Survey:fgqyjzspc92n2nwb8d7d
\ No newline at end of file diff --git a/data_science/cortex/utils/general_functions/index.html b/data_science/cortex/utils/general_functions/index.html index cb7b0360ea..f4e5d6dcb8 100644 --- a/data_science/cortex/utils/general_functions/index.html +++ b/data_science/cortex/utils/general_functions/index.html @@ -10,8 +10,8 @@ - - + + +
"U1234567890"
\ No newline at end of file diff --git a/data_science/cortex/utils/miscellaneous/index.html b/data_science/cortex/utils/miscellaneous/index.html index f0eda3293e..62cfd5b87a 100644 --- a/data_science/cortex/utils/miscellaneous/index.html +++ b/data_science/cortex/utils/miscellaneous/index.html @@ -10,8 +10,8 @@ - - + + +
{
"device_type": "iOS",
"os_version": "14.7.1",
"phone_type": "iPhone12,1"
}
\ No newline at end of file diff --git a/data_science/cortex/utils/module_scheduler/index.html b/data_science/cortex/utils/module_scheduler/index.html index 75531acf15..64ac1b06d8 100644 --- a/data_science/cortex/utils/module_scheduler/index.html +++ b/data_science/cortex/utils/module_scheduler/index.html @@ -10,8 +10,8 @@ - - + + +
utils.module_scheduler.unschedule_specific_survey("U1234567890", "Gratitude Journal Day 3")
\ No newline at end of file diff --git a/data_science/cortex/utils/notifications/index.html b/data_science/cortex/utils/notifications/index.html index 36d5252906..95c3542da1 100644 --- a/data_science/cortex/utils/notifications/index.html +++ b/data_science/cortex/utils/notifications/index.html @@ -10,8 +10,8 @@ - - + + +
cortex.notifications.slack('This is a test slack. Have a great day.')
\ No newline at end of file diff --git a/data_science/cortex/utils/sensors/index.html b/data_science/cortex/utils/sensors/index.html index f77bca3cdd..8fecebaaaf 100644 --- a/data_science/cortex/utils/sensors/index.html +++ b/data_science/cortex/utils/sensors/index.html @@ -10,8 +10,8 @@ - - + + +
utils.useful_functions.add_sensor("U1234567890", "lamp.gps", "GPS sensor")
\ No newline at end of file diff --git a/data_science/cortex/visualizations/basic_analysis/index.html b/data_science/cortex/visualizations/basic_analysis/index.html index c0487f6bbc..941f923d45 100644 --- a/data_science/cortex/visualizations/basic_analysis/index.html +++ b/data_science/cortex/visualizations/basic_analysis/index.html @@ -10,8 +10,8 @@ - - + +

Basic Analysis

@@ -43,6 +43,6 @@

Com

Logistic regression model

Finally, we fit a logistic regression model to predict which participants improved. The model achieved an AUC of 0.862 and had three non-zero coefficients:

FeatureCoefficient
entropy0.468
screen_duration0.212
sleep_duration0.223
-

From here, we can take a deeper look at why some features may be different across groups or investigate the relationships between correlated variables. The goal of these visualizations is to provide a starting point for further analysis.

+

From here, we can take a deeper look at why some features may be different across groups or investigate the relationships between correlated variables. The goal of these visualizations is to provide a starting point for further analysis.

\ No newline at end of file diff --git a/data_science/cortex/visualizations/data_quality/index.html b/data_science/cortex/visualizations/data_quality/index.html index dabcb26e75..94f861361a 100644 --- a/data_science/cortex/visualizations/data_quality/index.html +++ b/data_science/cortex/visualizations/data_quality/index.html @@ -10,8 +10,8 @@ - - + + +
visualizations.data_quality.clear_chart(researcher_id="abcdefg1234", name="data_quality_graph")
\ No newline at end of file diff --git a/data_science/cortex/visualizations/participant_level/index.html b/data_science/cortex/visualizations/participant_level/index.html index 6155a83ca4..ebfb73cf15 100644 --- a/data_science/cortex/visualizations/participant_level/index.html +++ b/data_science/cortex/visualizations/participant_level/index.html @@ -10,8 +10,8 @@ - - + + +

\ No newline at end of file diff --git a/data_science/cortex/what_is_cortex/index.html b/data_science/cortex/what_is_cortex/index.html index ea3750ca0d..1b6e8caf3c 100644 --- a/data_science/cortex/what_is_cortex/index.html +++ b/data_science/cortex/what_is_cortex/index.html @@ -10,8 +10,8 @@ - - + +

What is Cortex?

@@ -55,6 +55,6 @@

Sleep Suite<

Cortex provides daily estimated sleep duration for users, derived from sensor data. Estimates are customized to each user’s individual behavior, as Cortex finds their most common sleep window. The sleep estimation method is highly reliant on accelerometer data in particular, so users must have data from this sensor in order for Cortex to provide an accurate estimate. From this sensor data Cortex also provides estimates for time spent in active and sedentary states.

Mobility Suite

Cortex provides various features characterizing a user’s mobility in a given time window. Unlike the sleep estimates, the mobility suite can be used at any time scale, whether that is two minutes, hours, days, or months. Mobility features rely on GPS sensor data, so users must have data from this sensor in order for processing to successfully occur.

-

Mobility features belong to one of two categories: trips and significant locations. Trips provide information on discrete movement events that a user undergoes—e.g. commuting to work or going to the grocery store. Features included in this category are trip duration, distance and count. Significant locations provide information on places that users commonly visit. The coordinates of these locations is provided as well as the amount and fragmentation of time spent at each one, such as hometime location entropy, respectively.

+

Mobility features belong to one of two categories: trips and significant locations. Trips provide information on discrete movement events that a user undergoes—e.g. commuting to work or going to the grocery store. Features included in this category are trip duration, distance and count. Significant locations provide information on places that users commonly visit. The coordinates of these locations is provided as well as the amount and fragmentation of time spent at each one, such as hometime location entropy, respectively.

\ No newline at end of file diff --git a/data_science/data/index.html b/data_science/data/index.html index 4bbb511058..0ceacc0df4 100644 --- a/data_science/data/index.html +++ b/data_science/data/index.html @@ -10,8 +10,8 @@ - - + +
+
\ No newline at end of file diff --git a/data_science/data_portal/index.html b/data_science/data_portal/index.html index 2e2de34f4b..92d51aeb57 100644 --- a/data_science/data_portal/index.html +++ b/data_science/data_portal/index.html @@ -10,8 +10,8 @@ - - + +

Using the LAMP Data Portal

@@ -70,6 +70,6 @@

Data Portal Usage Examples

Example 4: Use an array of charts to examine a participant's data in great detail. Here, find examples of summary graphs which show changes over time, correlation heatmaps which highlight connections between different LAMP measures (outlined in red), and the activity tracking functionality seen in example 3.

Help & Updates

-

The LAMP data portal is currently in alpha, as is this documentation. We are actively seeking both feedback and requests about the usability and usefulness of the data portal and this documentation. Please give us any questions, comments, or feature requests either through our community page or our public GitHub repository

+

The LAMP data portal is currently in alpha, as is this documentation. We are actively seeking both feedback and requests about the usability and usefulness of the data portal and this documentation. Please give us any questions, comments, or feature requests either through our community page or our public GitHub repository

\ No newline at end of file diff --git a/data_science/data_types/activity_types/index.html b/data_science/data_types/activity_types/index.html index 1536124885..f6ae57f097 100644 --- a/data_science/data_types/activity_types/index.html +++ b/data_science/data_types/activity_types/index.html @@ -10,8 +10,8 @@ - - + + +
\ No newline at end of file diff --git a/data_science/data_types/sensor_types/index.html b/data_science/data_types/sensor_types/index.html index 8653541298..7203bb3933 100644 --- a/data_science/data_types/sensor_types/index.html +++ b/data_science/data_types/sensor_types/index.html @@ -10,8 +10,8 @@ - - + + +
{
'timestamp': 1609796944931,
'sensor': 'lamp.magnetometer',
'data': {
'x': -25.963943481445312,
'y': -2.191162109375,
'z': -403.3388977050781
}
}
\ No newline at end of file diff --git a/data_science/intro/index.html b/data_science/intro/index.html index 40ada3aecf..315daa5914 100644 --- a/data_science/intro/index.html +++ b/data_science/intro/index.html @@ -10,8 +10,8 @@ - - + + +
R -e 'install.packages("devtools"); devtools::install_github("BIDMCDigitalPsychiatry/LAMP-r")'
\ No newline at end of file diff --git a/data_science/jsonata/index.html b/data_science/jsonata/index.html index b9b011954f..673a49e856 100644 --- a/data_science/jsonata/index.html +++ b/data_science/jsonata/index.html @@ -10,8 +10,8 @@ - - + +

Using Document Transformations

@@ -635,6 +635,6 @@

Generic mat
  • next() - when invoked, will return details of the second occurrence of any matching substring (and so on).
  • In this example, invoking next() will return:

    -
    {
    "match": "canal",
    "start": 17,
    "end": 22,
    "groups": [],
    "next": "<native function>#0"
    }
    ```

    and so on, until it eventually returns the empty sequence.

    ## Writing a custom matcher

    We've learned that the regex syntax is just a function generator, and the signature and return structure of the generated 'matcher' function is well defined. The four regex-aware functions (`$match`, `$contain`, `$split`, `$replace`) simply invoke this function as part of their implementation. Apart from that, they have no awareness that these matcher functions were generated by the regex syntax.

    So it's possible to write any user-defined matcher function, provided it conforms to this contract. This can be done as a JSONata lambda function or (more likely) as an extension function. It can then be passed to these four 'regex-aware' functions and they will search using the custom matcher rather than a regex.

    # Date/Time processing

    ## The 'evaluation time’ - $now()

    There are two functions that return the 'current' date/time timestamp:

    1. [`$now()`](#now) returns the timestamp in an ISO 8601 formatted string.
    2. [`$millis()`](#millis) returns the same timestamp as the number of milliseconds since midnight on 1st January 1970 UTC (the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time)).

    The timestamp is captured at the start of the expression evaluation, and that same timestamp value is returned for every occurrence of `$now()` and `$millis()` in the same expression for the duration of the evaluation.

    __Example__

    - The timestamp will be the same for all invocations within an expression

    **Query**
    ```
    {
    "invoiceTime": $now(),
    "total": $sum(Account.Order.Product.(Price * Quantity)),
    "closingTime": $now()
    }
    ```
    **Result**
    ```
    {
    "invoiceTime": "2018-12-10T13:49:51.141Z",
    "total": 336.36,
    "closingTime": "2018-12-10T13:49:51.141Z"
    }
    ```

    ## JSON and ISO 8601

    JSON does not have a built-in type for date/time values. The general [consensus](https://stackoverflow.com/a/15952652/7079134) is to store the date/time value as a string in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.

    __Example__

    ```
    {
    "myDateTime": "2018-12-10T13:45:00.000Z"
    }
    ```

    JSONata follows this convention and provides functions for formatting and parsing ISO 8601 formatted timestamps
    ([`toMillis()`](#tomillis) and [`fromMillis()`](#frommillis))

    ## Support for other date/time formats

    Since there is no standard for date/time format in JSON, it is entirely possible that the JSON data you are working with will have date/time values formatted in other ways. JSONata supports the highly versatile picture string notation from the XPath/XQuery [fn:format-dateTime()](https://www.w3.org/TR/xpath-functions-31/#func-format-dateTime) specification for both the formatting and parsing of a wide variety of date/time formats.

    See [`toMillis()`](#tomillis) and [`fromMillis()`](#frommillis) for details.

    __Examples__

    - The date `12/10/2018` in US format and `10/12/2018` in European format both refer to the same day.

    **Query**
    ```
    $toMillis('10/12/2018', '[D]/[M]/[Y]') ~> $fromMillis('[M]/[D]/[Y]')
    ```
    **Result**
    ```
    "12/10/2018"
    ```

    - More verbose format.

    **Query**
    ```
    $toMillis('10/12/2018', '[D]/[M]/[Y]')
    ~> $fromMillis('[FNn], [D1o] [MNn] [YI]')
    ```
    **Result**
    ```
    "Monday, 10th December MMXVIII"
    ```


    # Path Operators

    The path operators underpin the declarative nature of the map/filter/reduce processing model in JSONata.

    ## `.` (Map)

    The dot operator is one of the fundamental building blocks in JSONata expressions. It implements the 'for each' or 'map' function that is common in many functional languages.

    The dot operator performs the following logic:

    - The expression on the LHS is evaluated to produce an array of values.
    - If it evaluates to a single value, that is treated as equivalent to an array containing that single value
    - If it evaluates to nothing (no match or empty array), then the result of the operator expression is nothing
    - For each value in the LHS array in turn:
    - The value is known as the _context_ and is used as the basis for any relative path expression on the RHS. It is also accessible in the RHS expression using the `$` symbol.
    - The RHS expression is evaluated to produce a value or array of values (or nothing). These values are appended to a combined array of results for the operator as a whole.
    - The combined result of the operator is returned.

    This operator is left associative meaning that the expression `a.b.c.d` is evaluated like `((a.b).c).d`; i.e. left to right

    __Examples__

    - `Address.City` => `"Winchester"`
    - `Phone.number` => `[ "0203 544 1234", "01962 001234", "01962 001235", "077 7700 1234" ]`
    - `Account.Order.Product.(Price * Quantity)` => `[ 68.9, 21.67, 137.8, 107.99 ]`
    - `Account.Order.OrderID.$uppercase()` => `[ "ORDER103", "ORDER104"]`

    ## `[` ... `]` (Filter)

    The filter operator (a.k.a predicate) is used to select only the items in the input sequence that satisfy the predicate expression contained between the square brackets.

    If the predicate expression is an integer, or an expression that evaluates to an integer, then the item at that position (zero offset) in the input sequence is the only item selected for the result sequence.
    If the number is non-integer, then it is rounded _down_ to the nearest integer.

    If the predicate expression is an array of integers, or an expression that evaluates to an array of integers, then the items at those positions (zero offset) in the input sequence is the only item selected for the result sequence.

    If the predicate expression evaluates to any other value, then it is cast to a Boolean as if using the `$boolean()` function. If this evaluates to `true`, then the item is retained in the result sequence. Otherwise it is rejected.

    See [Navigating JSON Arrays](#navigating-json-arrays) and [Predicates](#predicate) for more details and examples.

    ## `^(` ... `)` (Order-by)

    The order-by operator is used to sort an array of values into ascending or descending order according to one or more expressions defined within the parentheses.

    By default, the array will be sorted into ascending order. For example:

    `Account.Order.Product^(Price)`

    sorts all of the products into order of increasing price (`Price` is a numeric field in the `Product` object).

    To sort in descending order, the sort expression must be preceded by the `>` symbol. For example:

    `Account.Order.Product^(>Price)`

    sorts all of the products into order of decreasing price. The `<` symbol can be used to explicitly indicate ascending order, although that is the default behaviour.

    Secondary (and more) sort expressions can be specified by separating them with commas (`,`). The secondary expression will be used to determine order if the primary expression ranks two values the same. For example,

    `Account.Order.Product^(>Price, <Quantity)`

    orders the products primarily by decreasing price, but for products of the same price, by increasing quantity.

    The sort expression(s) can be any valid JSONata expression that evaluates to a number or a string. If it evaluates to a string then the array is sorted in order of unicode codepoint.

    __Examples__

    - `Account.Order.Product^(Price * Quantity)` => Increasing order of price times quantity.
    - `student[type='fulltime']^(DoB).name` => The names of all full time students sorted by date of birth (the DoB value is an ISO 8601 date format)

    ## `{` ... `}` (Reduce)

    The reduce operator can be used as the last step in a path expression to group and aggregate its input sequence into a single object.
    The key/value pairs between the curly braces determine the groupings (by evaluating the key expression) and the aggregated values for each group.
    See [Grouping and Aggregation](#grouping) for more details.


    ## `*` (Wildcard)

    This wildcard selects the values of all the properties of the context object. It can be used in a path expression in place of a property name, but it cannot be combined with other characters like a glob pattern. The order of these values in the result sequence is implementation dependent.
    See [Wildcards](#wildcards) for examples.

    ## `**` (Descendants)

    This wildcard recursively selects the values of all the properties of the context object, and the properties of any objects contained within these values as it descends the hierarchy.
    See [Navigate arbitrary depths](#navigate-arbitrary-depths).

    ## `%` (Parent)

    This will select the 'parent' of the current context value. Here, we define 'parent' to be the enclosing object which has the property representing the context value.

    This is the only operation which searches 'backwards' in the input data structure. It is implemented by static analysis of the expression at [compile time](https://docs.jsonata.org/embedding-extending#jsonatastr) and can only be used within expressions that navigate through that target parent value in the first place.
    If, for any reason, the parent location cannot be determined, then a static error (S0217) is thrown.

    __Example__

    ```
    Account.Order.Product.{
    'Product': `Product Name`,
    'Order': %.OrderID,
    'Account': %.%.`Account Name`
    }
    ```
    This returns an array of objects for each product in each order in each account. Information from the enclosing Order and Account objects can be accessed using the parent operator.
    The repeated combination of `%.%.` is used to access the grandparent and higher ancestors.


    ## `#` (Positional variable binding)

    This can be used to determine at which position in the sequence the current context item is. It can be used following any map, filter or order-by stage in the path.
    The variable is available for use within subsequent stages of the path (e.g. within filter predicates) and goes out of scope at the end of the path expression.

    __Example__

    ```
    library.books#$i['Kernighan' in authors].{
    'title': title,
    'index': $i
    }
    ```
    This returns an array of objects for each book in the library where Kernighan is one of the authors. Each object contains the book's title and its position within the books array before it was filtered.


    ## `@` (Context variable binding)

    This is used to bind the current context item (`$`) to a named variable. It can only be used directly following a map stage, not a filter or order-by stage.
    The variable binding remains in scope for the remainder of the path expression.

    Because the current context has now been explicitly bound to a named variable, this context will be carried forward to be the context of the next stage in the path.
    For example, in this snippet of a path, `library.loans@$l.books`, the loans array is a property of the library object and each loan will, in turn, be bound to the variable `$l`.
    The books array, which is also a property of the library object, will then be selected.

    This operator can be used to perform data joins within a path because of its ability to do cross-referencing across objects.

    __Example__

    ```
    library.loans@$l.books@$b[$l.isbn=$b.isbn].{
    'title': $b.title,
    'customer': $l.customer
    }
    ```
    This performs an 'inner join' between objects in the loans array and objects in the books array where the ISBNs match between the structures.

    Block expressions can be used to widen the scope of the data cross-referencing as shown in this example:

    ```
    (library.loans)@$l.(catalog.books)@$b[$l.isbn=$b.isbn].{
    'title': $b.title,
    'customer': $l.customer
    }
    ```

    # Numeric Operators

    ## `+` (Addition)

    The addition operator adds the operands to produce the numerical sum. It is an error if either operand is not a number.

    __Example__

    `5 + 2` => `7`


    ## `-` (Substraction/Negation)

    The subtraction operator subtracts the RHS value from the LHS value to produce the numerical difference It is an error if either operand is not a number.

    It can also be used in its unary form to negate a number

    __Examples__

    - `5 - 2` => `3`
    - `- 42` => `-42`

    ## `*` (Multiplication)

    The multiplication operator multiplies the operands to produce the numerical product. It is an error if either operand is not a number.

    __Example__

    `5 * 2` => `10`

    ## `/` (Division)

    The division operator divides the RHS into the LHS to produce the numerical quotient. It is an error if either operand is not a number.

    __Example__

    `5 / 2` => `2.5`


    ## `%` (Modulo)

    The modulo operator divides the RHS into the LHS using whole number division to produce a whole number quotient and a remainder. This operator returns the remainder. It is an error if either operand is not a number.

    __Example__

    `5 % 2` => `1`

    ## `..` (Range)

    The sequence generation operator is used to create an array of monotonically increasing integer start with the number on the LHS and ending with the number on the RHS. It is an error if either operand does not evaluate to an integer. The sequence generator can only be used within an array constructor [].

    __Examples__

    - `[1..5]` => `[1, 2, 3, 4, 5]`
    - `[1..3, 7..9]` => `[1, 2, 3, 7, 8, 9]`
    - `[1..$count(Items)].("Item " & $)` => `["Item 1","Item 2","Item 3"]`
    - `[1..5].($*$)` => `[1, 4, 9, 16, 25]`

    # Comparison Operators

    ## `=` (Equals)

    The equality operator returns Boolean `true` if both operands are the same (type and value). Arrays and objects are checked for deep equality. Arrays must have the same values in the same order. Objects must have the same key/value pairs (order is not relevant). Otherwise it returns `false`.

    __Examples__

    - `1+1 = 2` => `true`
    - `"Hello" = "World"` => `false`

    ## `!=` (Not equals)

    The inequality operator returns Boolean `false` if both operands are the same (type and value, deep equality). Otherwise it returns `true`.

    __Examples__

    - `1+1 != 3` => `true`
    - `"Hello" != "World"` => `true`

    ## `>` (Greater than)

    The 'greater than' operator returns Boolean `true` if the LHS is numerically greater than the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 > 3` => `true`
    - `5 > 5` => `false`

    ## `<` (Less than)

    The 'less than' operator returns Boolean `true` if the LHS is numerically less than the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 < 3` => `false`
    - `5 < 5` => `false`


    ## `>=` (Greater than or equals)

    The 'greater than or equals' operator returns Boolean `true` if the LHS is numerically greater than or equal to the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 >= 3` => `true`
    - `5 >= 5` => `true`


    ## `<=` (Less than or equals)

    The 'less than or equals' operator returns Boolean `true` if the LHS is numerically less than or equal to the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 <= 3` => `false`
    - `5 <= 5` => `true`

    ## `in` (Inclusion)

    The array (sequence) inclusion operator returns Boolean `true` if the value of the LHS is included in the array of values on the RHS. Otherwise it returns `false`. If the RHS is a single value, then it is treated as a singleton array.

    __Examples__

    - `"world" in ["hello", "world"]` => `true`
    - `"hello" in "hello"` => `true`
    - `library.books["Aho" in authors].title`

    # Boolean Operators

    ## `and` (Boolean AND)

    The 'and' operator returns Boolean `true` if both operands evaluate to `true`. If either or both operands is not a Boolean type, then they are first cast to a Boolean using the rules of the `$boolean` function.

    __Example__

    `library.books["Aho" in authors and price < 50].title`

    ## `or` (Boolean OR)

    The 'or' operator returns Boolean `true` if either operand evaluates to `true`. If either or both operands is not a Boolean type, then they are first cast to a Boolean using the rules of the `$boolean` function.

    __Example__

    `library.books[price < 10 or section="diy"].title`

    __Please note that Boolean 'NOT' is a [function](#not), not an operator.__

    # Other Operators

    ## `&` (Concatenation)

    The string concatenation operator is used to join the string values of the operands into a single resultant string. If either or both of the operands are not strings, then they are first cast to string using the rules of the `$string` function.

    __Example__

    `"Hello" & "World"` => `"HelloWorld"`

    ## `? :` (Conditional)

    The conditional ternary operator is used to evaluate one of two alternative expressions based on the result of a predicate (test) condition. The operator takes the form:

    `<test_expr> ? <expr_T> : <expr_F>`

    The `<test_expr>` expression is first evaluated. If it evaluates to Boolean `true`, then the operator returns the result of evaluating the `<expr_T>` expression. Otherwise it returns the result of evaluating the `<expr_F>` expression. If `<test_expr>` evaluates to a non-Boolean value, then the value is first cast to Boolean using the rules of the `$boolean` function.

    __Example__

    `Price < 50 ? "Cheap" : "Expensive"`

    ## `:=` (Variable binding)

    The variable binding operator is used to bind the value of the RHS to the variable name defined on the LHS. The variable binding is scoped to the current block and any nested blocks. It is an error if the LHS is not a `$` followed by a valid variable name.

    __Examples__

    - `$five := 5`
    - `$square := function($n) { $n * $n }`

    ## `~>` (Chain)

    The function chaining operator is used in the situations where multiple nested functions need to be applied to a value, while making it easy to read. The value on the LHS is evaluated, then passed into the function on the RHS as its first argument. If the function has any other arguments, then these are passed to the function in parenthesis as usual. It is an error if the RHS is not a function, or an expression that evaluates to a function.

    __Examples__

    `$uppercase($substringBefore($substringAfter(Customer.Email, "@"), "."))`

    and

    `$sum(Account.Order.Product.(Price * Quantity))`

    can be more clearly written:

    `Customer.Email ~> $substringAfter("@") ~> $substringBefore(".") ~> $uppercase()`

    and

    `Account.Order.Product.(Price * Quantity) ~> $sum()`

    This operator can also be used in a more abstract form to define new functions based on a combination of existing functions. In this form, there is no value passed in on the LHS of the first function in the chain.

    For example, the expression

    ```
    (
    $uppertrim := $trim ~> $uppercase;
    $uppertrim(" Hello World ")
    )
    ```

    => `"HELLO WORLD"`

    creates a new function `$uppertrim` that performs `$trim` followed by `$uppercase`.


    ## `... ~> | ... | ... |` (Transform)

    The object transform operator is used to modify a copy of an object structure using a pattern/action syntax to target specific modifications while keeping the rest of the structure unchanged.

    The syntax has the following structure:

    `head ~> | location | update [, delete] |`

    where

    - `head` evaluates to the object that is to be copied and transformed
    - `location` evaluates to the part(s) within the copied object that are to be updated. The `location` expression is evaluated relative to the result of `head`. The result of evaluating `location` must be an object or array of objects.
    - `update` evaluates to an object that is merged into the object matched by each `location`. `update` is evaluated relative to the result of `location` and if `location` matched multiple objects, then the update gets evaluated for each one of these. The result of (each) update is merged into the result of `location`.
    - `delete` (optional) evaluates to a string or an array of strings. Each string is the name of the name/value pair in each object matched by `location` that is to be removed from the resultant object.

    The `~>` operator is the operator for function chaining and passes the value on the left hand side to the function on the right hand side as its first argument. The expression on the right hand side must evaluate to a function, hence the `|...|...|` syntax generates a function with one argument.

    Example:

    `| Account.Order.Product | {'Price': Price * 1.2} |`

    defines a transform that will return a deep copy the object passed to it, but with the `Product` object modified such that its `Price` property has had its value increased by 20%. The first part of the expression is the path location that specifies all of the objects within the overall object to change, and the second part defines an object that will get merged into the object(s) matched by the first part. The merging semantics is the same as that of the `$merge()` function.

    This transform definition syntax creates a JSONata function which you can either assign to a variable and use multiple times, or invoke inline.
    Example:

    `payload ~> |Account.Order.Product|{'Price': Price * 1.2}|`

    or:

    `$increasePrice := |Account.Order.Product|{'Price': Price * 1.2}|`

    This also has the benefit that multiple transforms can be chained together for more complex transformations.

    In common with `$merge()`, multiple changes (inserts or updates) can be made to an object.
    Example:

    `|Account.Order.Product|{'Price': Price * 1.2, 'Total': Price * Quantity}|`

    Note that the Total will be calculated using the original price, not the modified one (JSONata is declarative not imperative).

    Properties can also be removed from objects. This is done using the optional `delete` clause which specifies the name(s) of the properties to delete.
    Example:

    `$ ~> |Account.Order.Product|{'Total': Price * Quantity}, ['Price', 'Quantity']|`

    This copies the input, but for each `Product` it inserts a Total and removes the `Price` and `Quantity` properties.

    # String functions

    ## `$string()`
    __Signature:__ `$string(arg, prettify)`

    Casts the `arg` parameter to a string using the following casting rules

    - Strings are unchanged
    - Functions are converted to an empty string
    - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number
    - All other values are converted to a JSON string using the [JSON.stringify](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) function

    If `arg` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `arg`.

    If `prettify` is true, then "prettified" JSON is produced. i.e One line per field and lines will be indented based on the field depth.

    __Examples__

    - `$string(5)` => `"5"`
    - `[1..5].$string()` => `["1", "2", "3", "4", "5"]`

    ## `$length()`
    __Signature:__ `$length(str)`

    Returns the number of characters in the string `str`. If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$length("Hello World")` => `11`

    ## `$substring()`
    __Signature:__ `$substring(str, start[, length])`

    Returns a string containing the characters in the first parameter `str` starting at position `start` (zero-offset). If `str` is not specified (i.e. this function is invoked with only the numeric argument(s)), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    If `length` is specified, then the substring will contain maximum `length` characters.

    If `start` is negative then it indicates the number of characters from the end of `str`. See [substr](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr) for full definition.

    __Examples__

    - `$substring("Hello World", 3)` => `"lo World"`
    - `$substring("Hello World", 3, 5)` => `"lo Wo"`
    - `$substring("Hello World", -4)` => `"orld"`
    - `$substring("Hello World", -4, 2)` => `"or"`

    ## `$substringBefore()`
    __Signature:__ `$substringBefore(str, chars)`

    Returns the substring before the first occurrence of the character sequence `chars` in `str`. If `str` is not specified (i.e. this function is invoked with only one argument), then the context value is used as the value of `str`. If `str` does not contain `chars`, then it returns `str`. An error is thrown if `str` and `chars` are not strings.

    __Examples__

    - `$substringBefore("Hello World", " ")` => `"Hello"`

    ## `$substringAfter()`
    __Signature:__ `$substringAfter(str, chars)`

    Returns the substring after the first occurrence of the character sequence `chars` in `str`. If `str` is not specified (i.e. this function is invoked with only one argument), then the context value is used as the value of `str`. If `str` does not contain `chars`, then it returns `str`. An error is thrown if `str` and `chars` are not strings.

    __Examples__

    - `$substringAfter("Hello World", " ")` => `"World"`


    ## `$uppercase()`
    __Signature:__ `$uppercase(str)`

    Returns a string with all the characters of `str` converted to uppercase. If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$uppercase("Hello World")` => `"HELLO WORLD"`


    ## `$lowercase()`
    __Signature:__ `$lowercase(str)`

    Returns a string with all the characters of `str` converted to lowercase. If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$lowercase("Hello World")` => `"hello world"`

    ## `$trim()`
    __Signature:__ `$trim(str)`

    Normalizes and trims all whitespace characters in `str` by applying the following steps:

    - All tabs, carriage returns, and line feeds are replaced with spaces.
    - Contiguous sequences of spaces are reduced to a single space.
    - Trailing and leading spaces are removed.

    If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$trim(" Hello \n World ")` => `"Hello World"`


    ## `$pad()`
    __Signature:__ `$pad(str, width [, char])`

    Returns a copy of the string `str` with extra padding, if necessary, so that its total number of characters is at least the absolute value of the `width` parameter. If `width` is a positive number, then the string is padded to the right; if negative, it is padded to the left. The optional `char` argument specifies the padding character(s) to use. If not specified, it defaults to the space character.

    __Examples__

    - `$pad("foo", 5)` => `"foo "`
    - `$pad("foo", -5)` => `" foo"`
    - `$pad("foo", -5, "#")` => `"##foo"`
    - `$formatBase(35, 2) ~> $pad(-8, '0')` => `"00100011"`


    ## `$contains()`
    __Signature:__ `$contains(str, pattern)`

    Returns `true` if `str` is matched by `pattern`, otherwise it returns `false`. If `str` is not specified (i.e. this function is invoked with one argument), then the context value is used as the value of `str`.

    The `pattern` parameter can either be a string or a regular expression (regex). If it is a string, the function returns `true` if the characters within `pattern` are contained contiguously within `str`. If it is a regex, the function will return `true` if the regex matches the contents of `str`.

    __Examples__

    - `$contains("abracadabra", "bra")` => `true`
    - `$contains("abracadabra", /a.*a/)` => `true`
    - `$contains("abracadabra", /ar.*a/)` => `false`
    - `$contains("Hello World", /wo/)` => `false`
    - `$contains("Hello World", /wo/i)` => `true`
    - `Phone[$contains(number, /^077/)]` => `{ "type": "mobile", "number": "077 7700 1234" }`

    ## `$split()`
    __Signature:__ `$split(str, separator [, limit])`

    Splits the `str` parameter into an array of substrings. If `str` is not specified, then the context value is used as the value of `str`. It is an error if `str` is not a string.

    The `separator` parameter can either be a string or a regular expression (regex). If it is a string, it specifies the characters within `str` about which it should be split. If it is the empty string, `str` will be split into an array of single characters. If it is a regex, it splits the string around any sequence of characters that match the regex.

    The optional `limit` parameter is a number that specifies the maximum number of substrings to include in the resultant array. Any additional substrings are discarded. If `limit` is not specified, then `str` is fully split with no limit to the size of the resultant array. It is an error if `limit` is not a non-negative number.

    __Examples__

    - `$split("so many words", " ")` => `[ "so", "many", "words" ]`
    - `$split("so many words", " ", 2)` => `[ "so", "many" ]`
    - `$split("too much, punctuation. hard; to read", /[ ,.;]+/)` => `["too", "much", "punctuation", "hard", "to", "read"]`

    ## `$join()`
    __Signature:__ `$join(array[, separator])`

    Joins an array of component strings into a single concatenated string with each component string separated by the optional `separator` parameter.

    It is an error if the input array contains an item which isn't a string.

    If `separator` is not specified, then it is assumed to be the empty string, i.e. no separator between the component strings. It is an error if `separator` is not a string.

    __Examples__

    - `$join(['a','b','c'])` => `"abc"`
    - `$split("too much, punctuation. hard; to read", /[ ,.;]+/, 3) ~> $join(', ')` => `"too, much, punctuation"`

    ## `$match()`
    __Signature:__ `$match(str, pattern [, limit])`

    Applies the `str` string to the `pattern` regular expression and returns an array of objects, with each object containing information about each occurrence of a match withing `str`.

    The object contains the following fields:

    - `match` - the substring that was matched by the regex.
    - `index` - the offset (starting at zero) within `str` of this match.
    - `groups` - if the regex contains capturing groups (parentheses), this contains an array of strings representing each captured group.

    If `str` is not specified, then the context value is used as the value of `str`. It is an error if `str` is not a string.

    __Examples__

    `$match("ababbabbcc",/a(b+)/)` =>
    ```
    [
    {
    "match": "ab",
    "index": 0,
    "groups": ["b"]
    },
    {
    "match": "abb",
    "index": 2,
    "groups": ["bb"]
    },
    {
    "match": "abb",
    "index": 5,
    "groups": ["bb" ]
    }
    ]
    ```

    ## `$replace()`
    __Signature:__ `$replace(str, pattern, replacement [, limit])`

    Finds occurrences of `pattern` within `str` and replaces them with `replacement`.

    If `str` is not specified, then the context value is used as the value of `str`. It is an error if `str` is not a string.

    The `pattern` parameter can either be a string or a regular expression (regex). If it is a string, it specifies the substring(s) within `str` which should be replaced. If it is a regex, its is used to find .

    The `replacement` parameter can either be a string or a function. If it is a string, it specifies the sequence of characters that replace the substring(s) that are matched by `pattern`. If `pattern` is a regex, then the `replacement` string can refer to the characters that were matched by the regex as well as any of the captured groups using a `$` followed by a number `N`:

    - If `N = 0`, then it is replaced by substring matched by the regex as a whole.
    - If `N > 0`, then it is replaced by the substring captured by the Nth parenthesised group in the regex.
    - If `N` is greater than the number of captured groups, then it is replaced by the empty string.
    - A literal `$` character must be written as `$$` in the `replacement` string

    If the `replacement` parameter is a function, then it is invoked for each match occurrence of the `pattern` regex. The `replacement` function must take a single parameter which will be the object structure of a regex match as described in the `$match` function; and must return a string.

    The optional `limit` parameter, is a number that specifies the maximum number of replacements to make before stopping. The remainder of the input beyond this limit will be copied to the output unchanged.

    __Examples__


    **Query**
    ```
    $replace("John Smith and John Jones", "John", "Mr")
    ```
    **Result**
    ```
    "Mr Smith and Mr Jones"
    ```


    **Query**
    ```
    $replace("John Smith and John Jones", "John", "Mr", 1)
    ```
    **Result**
    ```
    "Mr Smith and John Jones"
    ```


    **Query**
    ```
    $replace("abracadabra", /a.*?a/, "*")
    ```
    **Result**
    ```
    "*c*bra"
    ```


    **Query**
    ```
    $replace("John Smith", /(\w+)\s(\w+)/, "$2, $1")
    ```
    **Result**
    ```
    "Smith, John"
    ```


    **Query**
    ```
    $replace("265USD", /([0-9]+)USD/, "$$$1")
    ```
    **Result**
    ```
    "$265"
    ```


    **Query**
    ```
    (
    $convert := function($m) {
    ($number($m.groups[0]) - 32) * 5/9 & "C"
    };
    $replace("temperature = 68F today", /(\d+)F/, $convert)
    )
    ```
    **Result**
    ```
    "temperature = 20C today"
    ```


    ## `$eval()`
    __Signature:__ `$eval(expr [, context])`

    Parses and evaluates the string `expr` which contains literal JSON or a JSONata expression using the current context as the context for evaluation.

    __Examples__


    **Query**
    ```
    $eval("[1,2,3]")
    ```
    **Result**
    ```
    [1, 2, 3]
    ```

    **Query**
    ```
    $eval('[1,$string(2),3]')
    ```
    **Result**
    ```
    [1,"2",3]
    ```


    Optionally override the context by specifying the second parameter

    ## `$base64encode()`
    __Signature:__ `$base64encode()`

    Converts an ASCII string to a base 64 representation. Each each character in the string is treated as a byte of binary data. This requires that all characters in the string are in the 0x00 to 0xFF range, which includes all characters in URI encoded strings. Unicode characters outside of that range are not supported.

    __Examples__

    - `$base64encode("myuser:mypass")` => `"bXl1c2VyOm15cGFzcw=="`


    ## `$base64decode()`
    __Signature:__ `$base64decode()`

    Converts base 64 encoded bytes to a string, using a UTF-8 Unicode codepage.

    __Examples__

    - `$base64decode("bXl1c2VyOm15cGFzcw==")` => `"myuser:mypass"`

    ## `$encodeUrlComponent()`
    __Signature:__ `$encodeUrlComponent(str)`

    Encodes a Uniform Resource Locator (URL) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.

    __Examples__

    - `$encodeUrlComponent("?x=test")` => `"%3Fx%3Dtest"`

    ## `$encodeUrl()`
    __Signature:__ `$encodeUrl(str)`

    Encodes a Uniform Resource Locator (URL) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.

    __Examples__

    - `$encodeUrl("https://mozilla.org/?x=шеллы")` => `"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"`

    ## `$decodeUrlComponent()`
    __Signature:__ `$decodeUrlComponent(str)`

    Decodes a Uniform Resource Locator (URL) component previously created by encodeUrlComponent.

    __Examples__

    - `$decodeUrlComponent("%3Fx%3Dtest")` => `"?x=test"`

    ## `$decodeUrl()`
    __Signature:__ `$decodeUrl(str)`

    Decodes a Uniform Resource Locator (URL) previously created by encodeUrl.

    __Examples__

    - `$decodeUrl("https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B")` => `"https://mozilla.org/?x=шеллы"`

    # Numeric functions

    ## `$number()`
    __Signature:__ `$number(arg)`

    Casts the `arg` parameter to a number using the following casting rules
    - Numbers are unchanged
    - Strings that contain a sequence of characters that represent a legal JSON number are converted to that number
    - Boolean `true` casts to `1`, Boolean `false` casts to `0`
    - All other values cause an error to be thrown.

    If `arg` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `arg`.

    __Examples__
    - `$number("5")` => `5`
    - `["1", "2", "3", "4", "5"].$number()` => `[1, 2, 3, 4, 5]`


    ## `$abs()`
    __Signature:__ `$abs(number)`

    Returns the absolute value of the `number` parameter, i.e. if the number is negative, it returns the positive value.

    If `number` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `number`.

    __Examples__
    - `$abs(5)` => `5`
    - `$abs(-5)` => `-5`

    ## `$floor()`
    __Signature:__ `$floor(number)`

    Returns the value of `number` rounded down to the nearest integer that is smaller or equal to `number`.

    If `number` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `number`.

    __Examples__
    - `$floor(5)` => `5`
    - `$floor(5.3)` => `5`
    - `$floor(5.8)` => `5`
    - `$floor(-5.3)` => `-6`


    ## `$ceil()`
    __Signature:__ `$ceil(number)`

    Returns the value of `number` rounded up to the nearest integer that is greater than or equal to `number`.

    If `number` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `number`.

    __Examples__
    - `$ceil(5)` => `5`
    - `$ceil(5.3)` => `6`
    - `$ceil(5.8)` => `6`
    - `$ceil(-5.3)` => `-5`


    ## `$round()`
    __Signature:__ `$round(number [, precision])`

    Returns the value of the `number` parameter rounded to the number of decimal places specified by the optional `precision` parameter.

    The `precision` parameter (which must be an integer) species the number of decimal places to be present in the rounded number. If `precision` is not specified then it defaults to the value `0` and the number is rounded to the nearest integer. If `precision` is negative, then its value specifies which column to round to on the left side of the decimal place

    This function uses the [Round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even) strategy to decide which way to round numbers that fall exactly between two candidates at the specified precision. This strategy is commonly used in financial calculations and is the default rounding mode in IEEE 754.

    __Examples__
    - `$round(123.456)` => `123`
    - `$round(123.456, 2)` => `123.46`
    - `$round(123.456, -1)` => `120`
    - `$round(123.456, -2)` => `100`
    - `$round(11.5)` => `12`
    - `$round(12.5)` => `12`
    - `$round(125, -1)` => `120`

    ## `$power()`
    __Signature:__ `$power(base, exponent)`

    Returns the value of `base` raised to the power of `exponent` (<code>base<sup>exponent</sup></code>).

    If `base` is not specified (i.e. this function is invoked with one argument), then the context value is used as the value of `base`.

    An error is thrown if the values of `base` and `exponent` lead to a value that cannot be represented as a JSON number (e.g. Infinity, complex numbers).

    __Examples__
    - `$power(2, 8)` => `256`
    - `$power(2, 0.5)` => `1.414213562373`
    - `$power(2, -2)` => `0.25`

    ## `$sqrt()`
    __Signature:__ `$sqrt(number)`

    Returns the square root of the value of the `number` parameter.

    If `number` is not specified (i.e. this function is invoked with one argument), then the context value is used as the value of `number`.

    An error is thrown if the value of `number` is negative.

    __Examples__
    - `$sqrt(4)` => `2`
    - `$sqrt(2)` => `1.414213562373`

    ## `$random()`
    __Signature:__ `$random()`

    Returns a pseudo random number greater than or equal to zero and less than one (<code>0 &#8804; n < 1</code>)

    __Examples__
    - `$random()` => `0.7973541067127`
    - `$random()` => `0.4029142127028`
    - `$random()` => `0.6558078550072`


    ## `$formatNumber()`
    __Signature:__ `$formatNumber(number, picture [, options])`

    Casts the `number` to a string and formats it to a decimal representation as specified by the `picture` string.

    The behaviour of this function is consistent with the XPath/XQuery function [fn:format-number](https://www.w3.org/TR/xpath-functions-31/#func-format-number) as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the number is formatted and has the [same syntax](https://www.w3.org/TR/xpath-functions-31/#syntax-of-picture-string) as fn:format-number.

    The optional third argument `options` is used to override the default locale specific formatting characters such as the decimal separator. If supplied, this argument must be an object containing name/value pairs specified in the [decimal format](https://www.w3.org/TR/xpath-functions-31/#defining-decimal-format) section of the XPath F&O 3.1 specification.

    __Examples__

    - `$formatNumber(12345.6, '#,###.00')` => `"12,345.60"`
    - `$formatNumber(1234.5678, "00.000e0")` => `"12.346e2"`
    - `$formatNumber(34.555, "#0.00;(#0.00)")` => `"34.56"`
    - `$formatNumber(-34.555, "#0.00;(#0.00)")` => `"(34.56)"`
    - `$formatNumber(0.14, "01%")` => `"14%"`
    - `$formatNumber(0.14, "###pm", {"per-mille": "pm"})` => `"140pm"`
    - `$formatNumber(1234.5678, "①①.①①①e①", {"zero-digit": "\u245f"})` => `"①②.③④⑥e②"`


    ## `$formatBase()`
    __Signature:__ `$formatBase(number [, radix])`

    Casts the `number` to a string and formats it to an integer represented in the number base specified by the `radix` argument. If `radix` is not specified, then it defaults to base 10. `radix` can be between 2 and 36, otherwise an error is thrown.

    __Examples__

    - `$formatBase(100, 2)` => `"1100100"`
    - `$formatBase(2555, 16)` => `"9fb"`


    ## `$formatInteger()`
    __Signature:__ `$formatInteger(number, picture)`

    Casts the `number` to a string and formats it to an integer representation as specified by the `picture` string.

    The behaviour of this function is consistent with the two-argument version of the XPath/XQuery function [fn:format-integer](https://www.w3.org/TR/xpath-functions-31/#func-format-integer) as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the number is formatted and has the same syntax as fn:format-integer.

    __Examples__

    - `$formatInteger(2789, 'w')` => `"two thousand, seven hundred and eighty-nine"`
    - `$formatInteger(1999, 'I')` => `"MCMXCIX"`

    ## `$parseInteger()`
    __Signature:__ `$parseInteger(string, picture)`

    Parses the contents of the `string` parameter to an integer (as a JSON number) using the format specified by the `picture` string.
    The picture string parameter has the same format as `$formatInteger`. Although the XPath specification does not have an equivalent
    function for parsing integers, this capability has been added to JSONata.

    __Examples__

    - `$parseInteger("twelve thousand, four hundred and seventy-six", 'w')` => `12476`
    - `$parseInteger('12,345,678', '#,##0')` => `12345678`

    # Numeric aggregation functions

    ## `$sum()`
    __Signature:__ `$sum(array)`

    Returns the arithmetic sum of an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$sum([5,1,3,7,4])` => `20`

    ## `$max()`
    __Signature:__ `$max(array)`

    Returns the maximum number in an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$max([5,1,3,7,4])` => `7`

    ## `$min()`
    __Signature:__ `$min(array)`

    Returns the minimum number in an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$min([5,1,3,7,4])` => `1`

    ## `$average()`
    __Signature:__ `$average(array)`

    Returns the mean value of an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$average([5,1,3,7,4])` => `4`

    # Boolean functions

    ## `$boolean()`
    __Signature:__ `$boolean(arg)`

    Casts the argument to a Boolean using the following rules:

    | Argument type | Result |
    | ------------- | ------ |
    | Boolean | unchanged |
    | string: empty | `false`|
    | string: non-empty | `true` |
    | number: 0 | `false`|
    | number: non-zero | `true` |
    | null | `false`|
    | array: empty | `false` |
    | array: contains a member that casts to `true` | `true` |
    | array: all members cast to `false` | `false` |
    | object: empty | `false` |
    | object: non-empty | `true` |
    | function | `false` |


    ## `$not()`
    __Signature:__ `$not(arg)`

    Returns Boolean NOT on the argument. `arg` is first cast to a boolean

    ## `$exists()`
    __Signature:__ `$exists(arg)`

    Returns Boolean `true` if the arg expression evaluates to a value, or `false` if the expression does not match anything (e.g. a path to a non-existent field reference).

    # Array Functions

    ## `$count()`
    __Signature:__ `$count(array)`

    Returns the number of items in the `array` parameter. If the `array` parameter is not an array, but rather a value of another JSON type, then the parameter is treated as a singleton array containing that value, and this function returns `1`.

    If `array` is not specified, then the context value is used as the value of `array`.

    __Examples__
    - `$count([1,2,3,1])` => `4`
    - `$count("hello")` => 1

    ## `$append()`
    __Signature:__ `$append(array1, array2)`

    Returns an array containing the values in `array1` followed by the values in `array2`. If either parameter is not an array, then it is treated as a singleton array containing that value.

    __Examples__
    - `$append([1,2,3], [4,5,6])` => `[1,2,3,4,5,6]`
    - `$append([1,2,3], 4)` => `[1,2,3,4]`
    - `$append("Hello", "World")` => `["Hello", "World"]`


    ## `$sort()`
    __Signature:__ `$sort(array [, function])`

    Returns an array containing all the values in the `array` parameter, but sorted into order. If no `function` parameter is supplied, then the `array` parameter must contain only numbers or only strings, and they will be sorted in order of increasing number, or increasing unicode codepoint respectively.

    If a comparator `function` is supplied, then is must be a function that takes two parameters:

    `function(left, right)`

    This function gets invoked by the sorting algorithm to compare two values `left` and `right`. If the value of `left` should be placed after the value of `right` in the desired sort order, then the function must return Boolean `true` to indicate a swap. Otherwise it must return `false`.

    __Example__
    ```
    $sort(Account.Order.Product, function($l, $r) {
    $l.Description.Weight > $r.Description.Weight
    })
    ```

    This sorts the products in order of increasing weight.

    The sorting algorithm is *stable* which means that values within the original array which are the same according to the comparator function will remain in the original order in the sorted array.

    ## `$reverse()`
    __Signature:__ `$reverse(array)`

    Returns an array containing all the values from the `array` parameter, but in reverse order.

    __Examples__
    - `$reverse(["Hello", "World"])` => `["World", "Hello"]`
    - `[1..5] ~> $reverse()` => `[5, 4, 3, 2, 1]`

    ## `$shuffle()`
    __Signature:__ `$shuffle(array)`

    Returns an array containing all the values from the `array` parameter, but shuffled into random order.

    __Examples__
    - `$shuffle([1..9])` => `[6, 8, 2, 3, 9, 5, 1, 4, 7]`

    ## `$distinct()`
    __Signature__ `$distinct(array)`

    Returns an array containing all the values from the `array` parameter, but with any duplicates removed. Values are tested for deep equality as if by using the [equality operator](#equals).

    __Examples__
    - `$distinct([1,2,3,3,4,3,5])` => `[1, 2, 3, 4, 5]`
    - `$distinct(Account.Order.Product.Description.Colour)` => `[ "Purple", "Orange", "Black" ]`

    ## `$zip()`
    __Signature:__ `$zip(array1, ...)`

    Returns a convolved (zipped) array containing grouped arrays of values from the `array1` ... `arrayN` arguments from index 0, 1, 2, etc.

    This function accepts a variable number of arguments. The length of the returned array is equal to the length of the shortest array in the arguments.

    __Examples__
    - `$zip([1,2,3], [4,5,6])` => `[[1,4] ,[2,5], [3,6]]`
    - `$zip([1,2,3],[4,5],[7,8,9])` => `[[1,4,7], [2,5,8]]`

    # Object functions

    ## `$keys()`
    __Signature:__ `$keys(object)`

    Returns an array containing the keys in the object. If the argument is an array of objects, then the array returned contains a de-duplicated list of all the keys in all of the objects.

    ## `$lookup()`
    __Signature:__ `$lookup(object, key)`

    Returns the value associated with `key` in `object`. If the first argument is an array of objects, then all of the objects in the array are searched, and the values associated with all occurrences of `key` are returned.


    ## `$spread()`
    __Signature:__ `$spread(object)`

    Splits an `object` containing key/value pairs into an array of objects, each of which has a single key/value pair from the input `object`. If the parameter is an array of objects, then the resultant array contains an object for every key/value pair in every object in the supplied array.

    ## `$merge()`
    __Signature:__ `$merge(array<object>)`

    Merges an array of objects into a single object containing all the key/value pairs from each of the objects in the input array. If any of the input objects contain the same key, then the returned object will contain the value of the last one in the array. It is an error if the input array contains an item that is not an object.

    ## `$sift()`
    __Signature:__ `$sift(object, function)`

    See definition under 'Higher-order functions'

    ## `$each()`
    __Signature:__ `$each(object, function)`

    Returns an array containing the values return by the `function` when applied to each key/value pair in the `object`.

    The `function` parameter will get invoked with two arguments:

    `function(value, name)`

    where the `value` parameter is the value of each name/value pair in the object and `name` is its name. The `name` parameter is optional.

    __Examples__

    `$each(Address, function($v, $k) {$k & ": " & $v})`

    =>

    [
    "Street: Hursley Park",
    "City: Winchester",
    "Postcode: SO21 2JN"
    ]

    ## `$error()`
    __Signature:__`$error(message)`

    Deliberately throws an error with an optional `message`

    ## `$assert()`
    __Signature:__`$assert(condition, message)`

    If condition is true, the function returns undefined. If the condition is false, an exception is thrown with the message as the message of the exception.

    ## `$type()`
    __Signature:__`$type(value)`

    Evaluates the type of `value` and returns one of the following strings:
    * `"null"`
    * `"number"`
    * `"string"`
    * `"boolean"`
    * `"array"`
    * `"object"`
    * `"function"`
    Returns (non-string) `undefined` when `value` is `undefined`.

    # Date/Time functions

    ## `$now()`
    __Signature:__ `$now([picture [, timezone]])`

    Generates a UTC timestamp in ISO 8601 compatible format and returns it as a string. All invocations of `$now()` within an evaluation of an expression will all return the same timestamp value.

    If the optional `picture` and `timezone` parameters are supplied, then the current timestamp is formatted as described by the [`$fromMillis()`](#frommillis) function.

    __Examples__

    - `$now()` => `"2017-05-15T15:12:59.152Z"`


    ## `$millis()`
    __Signature:__ `$millis()`

    Returns the number of milliseconds since the Unix *Epoch* (1 January, 1970 UTC) as a number. All invocations of `$millis()` within an evaluation of an expression will all return the same value.

    __Examples__
    - `$millis()` => `1502700297574`


    ## `$fromMillis()`
    __Signature:__ `$fromMillis(number [, picture [, timezone]])`

    Convert the `number` representing milliseconds since the Unix *Epoch* (1 January, 1970 UTC) to a formatted string representation of the timestamp as specified by the `picture` string.

    If the optional `picture` parameter is omitted, then the timestamp is formatted in the [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.

    If the optional `picture` string is supplied, then the timestamp is formatted occording to the representation specified in that string.
    The behaviour of this function is consistent with the two-argument version of the XPath/XQuery function [fn:format-dateTime](https://www.w3.org/TR/xpath-functions-31/#func-format-dateTime) as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the timestamp is formatted and has the [same syntax](https://www.w3.org/TR/xpath-functions-31/#date-picture-string) as fn:format-dateTime.

    If the optional `timezone` string is supplied, then the formatted timestamp will be in that timezone. The `timezone` string should be in the
    format "±HHMM", where ± is either the plus or minus sign and HHMM is the offset in hours and minutes from UTC. Positive offset for timezones
    east of UTC, negative offset for timezones west of UTC.

    __Examples__

    - `$fromMillis(1510067557121)` => `"2017-11-07T15:12:37.121Z"`
    - `$fromMillis(1510067557121, '[M01]/[D01]/[Y0001] [h#1]:[m01][P]')` => `"11/07/2017 3:12pm"`
    - `$fromMillis(1510067557121, '[H01]:[m01]:[s01] [z]', '-0500')` => `"10:12:37 GMT-05:00"`

    ## `$toMillis()`
    __Signature:__ `$toMillis(timestamp [, picture])`

    Convert a `timestamp` string to the number of milliseconds since the Unix *Epoch* (1 January, 1970 UTC) as a number.

    If the optional `picture` string is not specified, then the format of the timestamp is assumed to be [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). An error is thrown if the string is not in the correct format.

    If the `picture` string is specified, then the format is assumed to be described by this picture string using the [same syntax](https://www.w3.org/TR/xpath-functions-31/#date-picture-string) as the XPath/XQuery function [fn:format-dateTime](https://www.w3.org/TR/xpath-functions-31/#func-format-dateTime), defined in the XPath F&O 3.1 specification.

    __Examples__

    - `$toMillis("2017-11-07T15:07:54.972Z")` => `1510067274972`

    # Higher order functions

    ## `$map()`
    __Signature:__ `$map(array, function)`

    Returns an array containing the results of applying the `function` parameter to each value in the `array` parameter.

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, index [, array]])`

    Each value in the input array is passed in as the first parameter in the supplied function. The index (position) of that value in the input array is passed in as the second parameter, if specified. The whole input array is passed in as the third parameter, if specified.

    __Examples__
    - `$map([1..5], $string)` => `["1", "2", "3", "4", "5"]`

    With user-defined (lambda) function:
    ```
    $map(Email.address, function($v, $i, $a) {
    'Item ' & ($i+1) & ' of ' & $count($a) & ': ' & $v
    })
    ```

    evaluates to:

    ```
    [
    "Item 1 of 4: fred.smith@my-work.com",
    "Item 2 of 4: fsmith@my-work.com",
    "Item 3 of 4: freddy@my-social.com",
    "Item 4 of 4: frederic.smith@very-serious.com"
    ]
    ```

    ## `$filter()`
    __Signature:__ `$filter(array, function)`

    Returns an array containing only the values in the `array` parameter that satisfy the `function` predicate (i.e. `function` returns Boolean `true` when passed the value).

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, index [, array]])`

    Each value in the input array is passed in as the first parameter in the supplied function. The index (position) of that value in the input array is passed in as the second parameter, if specified. The whole input array is passed in as the third parameter, if specified.

    __Example__
    The following expression returns all the products whose price is higher than average:
    ```
    $filter(Account.Order.Product, function($v, $i, $a) {
    $v.Price > $average($a.Price)
    })
    ```

    ## `$single()`
    __Signature:__ `$single(array, function)`

    Returns the one and only one value in the `array` parameter that satisfy the `function` predicate (i.e. `function` returns Boolean `true` when passed the value). Throws an exception if the number of matching values is not exactly one.

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, index [, array]])`

    Each value in the input array is passed in as the first parameter in the supplied function. The index (position) of that value in the input array is passed in as the second parameter, if specified. The whole input array is passed in as the third parameter, if specified.

    __Example__
    The following expression the product in the order whose SKU is `"0406654608"`:
    ```
    $single(Account.Order.Product, function($v, $i, $a) {
    $v.SKU = "0406654608"
    })
    ```

    ## `$reduce()`
    __Signature:__ `$reduce(array, function [, init])`

    Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.

    The `function` must accept at least two arguments, and behaves like an infix operator between each value within the `array`. The signature of this supplied function must be of the form:

    `myfunc($accumulator, $value[, $index[, $array]])`

    __Example__

    ```
    (
    $product := function($i, $j){$i * $j};
    $reduce([1..5], $product)
    )
    ```

    This multiplies all the values together in the array `[1..5]` to return `120`.

    If the optional `init` parameter is supplied, then that value is used as the initial value in the aggregation (fold) process. If not supplied, the initial value is the first value in the `array` parameter.

    ## `$sift()`
    __Signature:__ `$sift(object, function)`

    Returns an object that contains only the key/value pairs from the `object` parameter that satisfy the predicate `function` passed in as the second parameter.

    If `object` is not specified, then the context value is used as the value of `object`. It is an error if `object` is not an object.

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, key [, object]])`

    Each value in the input object is passed in as the first parameter in the supplied function. The key (property name) of that value in the input object is passed in as the second parameter, if specified. The whole input object is passed in as the third parameter, if specified.

    __Example__

    ```
    Account.Order.Product.$sift(function($v, $k) {$k ~> /^Product/})
    ```

    This sifts each of the `Product` objects such that they only contain the fields whose keys start with the string "Product" (using a regex). This example returns:

    ```
    [
    {
    "Product Name": "Bowler Hat",
    "ProductID": 858383
    },
    {
    "Product Name": "Trilby hat",
    "ProductID": 858236
    },
    {
    "Product Name": "Bowler Hat",
    "ProductID": 858383
    },
    {
    "ProductID": 345664,
    "Product Name": "Cloak"
    }
    ]
    ```

    +
    {
    "match": "canal",
    "start": 17,
    "end": 22,
    "groups": [],
    "next": "<native function>#0"
    }
    ```

    and so on, until it eventually returns the empty sequence.

    ## Writing a custom matcher

    We've learned that the regex syntax is just a function generator, and the signature and return structure of the generated 'matcher' function is well defined. The four regex-aware functions (`$match`, `$contain`, `$split`, `$replace`) simply invoke this function as part of their implementation. Apart from that, they have no awareness that these matcher functions were generated by the regex syntax.

    So it's possible to write any user-defined matcher function, provided it conforms to this contract. This can be done as a JSONata lambda function or (more likely) as an extension function. It can then be passed to these four 'regex-aware' functions and they will search using the custom matcher rather than a regex.

    # Date/Time processing

    ## The 'evaluation time’ - $now()

    There are two functions that return the 'current' date/time timestamp:

    1. [`$now()`](#now) returns the timestamp in an ISO 8601 formatted string.
    2. [`$millis()`](#millis) returns the same timestamp as the number of milliseconds since midnight on 1st January 1970 UTC (the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time)).

    The timestamp is captured at the start of the expression evaluation, and that same timestamp value is returned for every occurrence of `$now()` and `$millis()` in the same expression for the duration of the evaluation.

    __Example__

    - The timestamp will be the same for all invocations within an expression

    **Query**
    ```
    {
    "invoiceTime": $now(),
    "total": $sum(Account.Order.Product.(Price * Quantity)),
    "closingTime": $now()
    }
    ```
    **Result**
    ```
    {
    "invoiceTime": "2018-12-10T13:49:51.141Z",
    "total": 336.36,
    "closingTime": "2018-12-10T13:49:51.141Z"
    }
    ```

    ## JSON and ISO 8601

    JSON does not have a built-in type for date/time values. The general [consensus](https://stackoverflow.com/a/15952652/7079134) is to store the date/time value as a string in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.

    __Example__

    ```
    {
    "myDateTime": "2018-12-10T13:45:00.000Z"
    }
    ```

    JSONata follows this convention and provides functions for formatting and parsing ISO 8601 formatted timestamps
    ([`toMillis()`](#tomillis) and [`fromMillis()`](#frommillis))

    ## Support for other date/time formats

    Since there is no standard for date/time format in JSON, it is entirely possible that the JSON data you are working with will have date/time values formatted in other ways. JSONata supports the highly versatile picture string notation from the XPath/XQuery [fn:format-dateTime()](https://www.w3.org/TR/xpath-functions-31/#func-format-dateTime) specification for both the formatting and parsing of a wide variety of date/time formats.

    See [`toMillis()`](#tomillis) and [`fromMillis()`](#frommillis) for details.

    __Examples__

    - The date `12/10/2018` in US format and `10/12/2018` in European format both refer to the same day.

    **Query**
    ```
    $toMillis('10/12/2018', '[D]/[M]/[Y]') ~> $fromMillis('[M]/[D]/[Y]')
    ```
    **Result**
    ```
    "12/10/2018"
    ```

    - More verbose format.

    **Query**
    ```
    $toMillis('10/12/2018', '[D]/[M]/[Y]')
    ~> $fromMillis('[FNn], [D1o] [MNn] [YI]')
    ```
    **Result**
    ```
    "Monday, 10th December MMXVIII"
    ```


    # Path Operators

    The path operators underpin the declarative nature of the map/filter/reduce processing model in JSONata.

    ## `.` (Map)

    The dot operator is one of the fundamental building blocks in JSONata expressions. It implements the 'for each' or 'map' function that is common in many functional languages.

    The dot operator performs the following logic:

    - The expression on the LHS is evaluated to produce an array of values.
    - If it evaluates to a single value, that is treated as equivalent to an array containing that single value
    - If it evaluates to nothing (no match or empty array), then the result of the operator expression is nothing
    - For each value in the LHS array in turn:
    - The value is known as the _context_ and is used as the basis for any relative path expression on the RHS. It is also accessible in the RHS expression using the `$` symbol.
    - The RHS expression is evaluated to produce a value or array of values (or nothing). These values are appended to a combined array of results for the operator as a whole.
    - The combined result of the operator is returned.

    This operator is left associative meaning that the expression `a.b.c.d` is evaluated like `((a.b).c).d`; i.e. left to right

    __Examples__

    - `Address.City` => `"Winchester"`
    - `Phone.number` => `[ "0203 544 1234", "01962 001234", "01962 001235", "077 7700 1234" ]`
    - `Account.Order.Product.(Price * Quantity)` => `[ 68.9, 21.67, 137.8, 107.99 ]`
    - `Account.Order.OrderID.$uppercase()` => `[ "ORDER103", "ORDER104"]`

    ## `[` ... `]` (Filter)

    The filter operator (a.k.a predicate) is used to select only the items in the input sequence that satisfy the predicate expression contained between the square brackets.

    If the predicate expression is an integer, or an expression that evaluates to an integer, then the item at that position (zero offset) in the input sequence is the only item selected for the result sequence.
    If the number is non-integer, then it is rounded _down_ to the nearest integer.

    If the predicate expression is an array of integers, or an expression that evaluates to an array of integers, then the items at those positions (zero offset) in the input sequence is the only item selected for the result sequence.

    If the predicate expression evaluates to any other value, then it is cast to a Boolean as if using the `$boolean()` function. If this evaluates to `true`, then the item is retained in the result sequence. Otherwise it is rejected.

    See [Navigating JSON Arrays](#navigating-json-arrays) and [Predicates](#predicate) for more details and examples.

    ## `^(` ... `)` (Order-by)

    The order-by operator is used to sort an array of values into ascending or descending order according to one or more expressions defined within the parentheses.

    By default, the array will be sorted into ascending order. For example:

    `Account.Order.Product^(Price)`

    sorts all of the products into order of increasing price (`Price` is a numeric field in the `Product` object).

    To sort in descending order, the sort expression must be preceded by the `>` symbol. For example:

    `Account.Order.Product^(>Price)`

    sorts all of the products into order of decreasing price. The `<` symbol can be used to explicitly indicate ascending order, although that is the default behaviour.

    Secondary (and more) sort expressions can be specified by separating them with commas (`,`). The secondary expression will be used to determine order if the primary expression ranks two values the same. For example,

    `Account.Order.Product^(>Price, <Quantity)`

    orders the products primarily by decreasing price, but for products of the same price, by increasing quantity.

    The sort expression(s) can be any valid JSONata expression that evaluates to a number or a string. If it evaluates to a string then the array is sorted in order of unicode codepoint.

    __Examples__

    - `Account.Order.Product^(Price * Quantity)` => Increasing order of price times quantity.
    - `student[type='fulltime']^(DoB).name` => The names of all full time students sorted by date of birth (the DoB value is an ISO 8601 date format)

    ## `{` ... `}` (Reduce)

    The reduce operator can be used as the last step in a path expression to group and aggregate its input sequence into a single object.
    The key/value pairs between the curly braces determine the groupings (by evaluating the key expression) and the aggregated values for each group.
    See [Grouping and Aggregation](#grouping) for more details.


    ## `*` (Wildcard)

    This wildcard selects the values of all the properties of the context object. It can be used in a path expression in place of a property name, but it cannot be combined with other characters like a glob pattern. The order of these values in the result sequence is implementation dependent.
    See [Wildcards](#wildcards) for examples.

    ## `**` (Descendants)

    This wildcard recursively selects the values of all the properties of the context object, and the properties of any objects contained within these values as it descends the hierarchy.
    See [Navigate arbitrary depths](#navigate-arbitrary-depths).

    ## `%` (Parent)

    This will select the 'parent' of the current context value. Here, we define 'parent' to be the enclosing object which has the property representing the context value.

    This is the only operation which searches 'backwards' in the input data structure. It is implemented by static analysis of the expression at [compile time](https://docs.jsonata.org/embedding-extending#jsonatastr) and can only be used within expressions that navigate through that target parent value in the first place.
    If, for any reason, the parent location cannot be determined, then a static error (S0217) is thrown.

    __Example__

    ```
    Account.Order.Product.{
    'Product': `Product Name`,
    'Order': %.OrderID,
    'Account': %.%.`Account Name`
    }
    ```
    This returns an array of objects for each product in each order in each account. Information from the enclosing Order and Account objects can be accessed using the parent operator.
    The repeated combination of `%.%.` is used to access the grandparent and higher ancestors.


    ## `#` (Positional variable binding)

    This can be used to determine at which position in the sequence the current context item is. It can be used following any map, filter or order-by stage in the path.
    The variable is available for use within subsequent stages of the path (e.g. within filter predicates) and goes out of scope at the end of the path expression.

    __Example__

    ```
    library.books#$i['Kernighan' in authors].{
    'title': title,
    'index': $i
    }
    ```
    This returns an array of objects for each book in the library where Kernighan is one of the authors. Each object contains the book's title and its position within the books array before it was filtered.


    ## `@` (Context variable binding)

    This is used to bind the current context item (`$`) to a named variable. It can only be used directly following a map stage, not a filter or order-by stage.
    The variable binding remains in scope for the remainder of the path expression.

    Because the current context has now been explicitly bound to a named variable, this context will be carried forward to be the context of the next stage in the path.
    For example, in this snippet of a path, `library.loans@$l.books`, the loans array is a property of the library object and each loan will, in turn, be bound to the variable `$l`.
    The books array, which is also a property of the library object, will then be selected.

    This operator can be used to perform data joins within a path because of its ability to do cross-referencing across objects.

    __Example__

    ```
    library.loans@$l.books@$b[$l.isbn=$b.isbn].{
    'title': $b.title,
    'customer': $l.customer
    }
    ```
    This performs an 'inner join' between objects in the loans array and objects in the books array where the ISBNs match between the structures.

    Block expressions can be used to widen the scope of the data cross-referencing as shown in this example:

    ```
    (library.loans)@$l.(catalog.books)@$b[$l.isbn=$b.isbn].{
    'title': $b.title,
    'customer': $l.customer
    }
    ```

    # Numeric Operators

    ## `+` (Addition)

    The addition operator adds the operands to produce the numerical sum. It is an error if either operand is not a number.

    __Example__

    `5 + 2` => `7`


    ## `-` (Substraction/Negation)

    The subtraction operator subtracts the RHS value from the LHS value to produce the numerical difference It is an error if either operand is not a number.

    It can also be used in its unary form to negate a number

    __Examples__

    - `5 - 2` => `3`
    - `- 42` => `-42`

    ## `*` (Multiplication)

    The multiplication operator multiplies the operands to produce the numerical product. It is an error if either operand is not a number.

    __Example__

    `5 * 2` => `10`

    ## `/` (Division)

    The division operator divides the RHS into the LHS to produce the numerical quotient. It is an error if either operand is not a number.

    __Example__

    `5 / 2` => `2.5`


    ## `%` (Modulo)

    The modulo operator divides the RHS into the LHS using whole number division to produce a whole number quotient and a remainder. This operator returns the remainder. It is an error if either operand is not a number.

    __Example__

    `5 % 2` => `1`

    ## `..` (Range)

    The sequence generation operator is used to create an array of monotonically increasing integer start with the number on the LHS and ending with the number on the RHS. It is an error if either operand does not evaluate to an integer. The sequence generator can only be used within an array constructor [].

    __Examples__

    - `[1..5]` => `[1, 2, 3, 4, 5]`
    - `[1..3, 7..9]` => `[1, 2, 3, 7, 8, 9]`
    - `[1..$count(Items)].("Item " & $)` => `["Item 1","Item 2","Item 3"]`
    - `[1..5].($*$)` => `[1, 4, 9, 16, 25]`

    # Comparison Operators

    ## `=` (Equals)

    The equality operator returns Boolean `true` if both operands are the same (type and value). Arrays and objects are checked for deep equality. Arrays must have the same values in the same order. Objects must have the same key/value pairs (order is not relevant). Otherwise it returns `false`.

    __Examples__

    - `1+1 = 2` => `true`
    - `"Hello" = "World"` => `false`

    ## `!=` (Not equals)

    The inequality operator returns Boolean `false` if both operands are the same (type and value, deep equality). Otherwise it returns `true`.

    __Examples__

    - `1+1 != 3` => `true`
    - `"Hello" != "World"` => `true`

    ## `>` (Greater than)

    The 'greater than' operator returns Boolean `true` if the LHS is numerically greater than the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 > 3` => `true`
    - `5 > 5` => `false`

    ## `<` (Less than)

    The 'less than' operator returns Boolean `true` if the LHS is numerically less than the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 < 3` => `false`
    - `5 < 5` => `false`


    ## `>=` (Greater than or equals)

    The 'greater than or equals' operator returns Boolean `true` if the LHS is numerically greater than or equal to the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 >= 3` => `true`
    - `5 >= 5` => `true`


    ## `<=` (Less than or equals)

    The 'less than or equals' operator returns Boolean `true` if the LHS is numerically less than or equal to the RHS. Otherwise it returns `false`.

    __Examples__

    - `22 / 7 <= 3` => `false`
    - `5 <= 5` => `true`

    ## `in` (Inclusion)

    The array (sequence) inclusion operator returns Boolean `true` if the value of the LHS is included in the array of values on the RHS. Otherwise it returns `false`. If the RHS is a single value, then it is treated as a singleton array.

    __Examples__

    - `"world" in ["hello", "world"]` => `true`
    - `"hello" in "hello"` => `true`
    - `library.books["Aho" in authors].title`

    # Boolean Operators

    ## `and` (Boolean AND)

    The 'and' operator returns Boolean `true` if both operands evaluate to `true`. If either or both operands is not a Boolean type, then they are first cast to a Boolean using the rules of the `$boolean` function.

    __Example__

    `library.books["Aho" in authors and price < 50].title`

    ## `or` (Boolean OR)

    The 'or' operator returns Boolean `true` if either operand evaluates to `true`. If either or both operands is not a Boolean type, then they are first cast to a Boolean using the rules of the `$boolean` function.

    __Example__

    `library.books[price < 10 or section="diy"].title`

    __Please note that Boolean 'NOT' is a [function](#not), not an operator.__

    # Other Operators

    ## `&` (Concatenation)

    The string concatenation operator is used to join the string values of the operands into a single resultant string. If either or both of the operands are not strings, then they are first cast to string using the rules of the `$string` function.

    __Example__

    `"Hello" & "World"` => `"HelloWorld"`

    ## `? :` (Conditional)

    The conditional ternary operator is used to evaluate one of two alternative expressions based on the result of a predicate (test) condition. The operator takes the form:

    `<test_expr> ? <expr_T> : <expr_F>`

    The `<test_expr>` expression is first evaluated. If it evaluates to Boolean `true`, then the operator returns the result of evaluating the `<expr_T>` expression. Otherwise it returns the result of evaluating the `<expr_F>` expression. If `<test_expr>` evaluates to a non-Boolean value, then the value is first cast to Boolean using the rules of the `$boolean` function.

    __Example__

    `Price < 50 ? "Cheap" : "Expensive"`

    ## `:=` (Variable binding)

    The variable binding operator is used to bind the value of the RHS to the variable name defined on the LHS. The variable binding is scoped to the current block and any nested blocks. It is an error if the LHS is not a `$` followed by a valid variable name.

    __Examples__

    - `$five := 5`
    - `$square := function($n) { $n * $n }`

    ## `~>` (Chain)

    The function chaining operator is used in the situations where multiple nested functions need to be applied to a value, while making it easy to read. The value on the LHS is evaluated, then passed into the function on the RHS as its first argument. If the function has any other arguments, then these are passed to the function in parenthesis as usual. It is an error if the RHS is not a function, or an expression that evaluates to a function.

    __Examples__

    `$uppercase($substringBefore($substringAfter(Customer.Email, "@"), "."))`

    and

    `$sum(Account.Order.Product.(Price * Quantity))`

    can be more clearly written:

    `Customer.Email ~> $substringAfter("@") ~> $substringBefore(".") ~> $uppercase()`

    and

    `Account.Order.Product.(Price * Quantity) ~> $sum()`

    This operator can also be used in a more abstract form to define new functions based on a combination of existing functions. In this form, there is no value passed in on the LHS of the first function in the chain.

    For example, the expression

    ```
    (
    $uppertrim := $trim ~> $uppercase;
    $uppertrim(" Hello World ")
    )
    ```

    => `"HELLO WORLD"`

    creates a new function `$uppertrim` that performs `$trim` followed by `$uppercase`.


    ## `... ~> | ... | ... |` (Transform)

    The object transform operator is used to modify a copy of an object structure using a pattern/action syntax to target specific modifications while keeping the rest of the structure unchanged.

    The syntax has the following structure:

    `head ~> | location | update [, delete] |`

    where

    - `head` evaluates to the object that is to be copied and transformed
    - `location` evaluates to the part(s) within the copied object that are to be updated. The `location` expression is evaluated relative to the result of `head`. The result of evaluating `location` must be an object or array of objects.
    - `update` evaluates to an object that is merged into the object matched by each `location`. `update` is evaluated relative to the result of `location` and if `location` matched multiple objects, then the update gets evaluated for each one of these. The result of (each) update is merged into the result of `location`.
    - `delete` (optional) evaluates to a string or an array of strings. Each string is the name of the name/value pair in each object matched by `location` that is to be removed from the resultant object.

    The `~>` operator is the operator for function chaining and passes the value on the left hand side to the function on the right hand side as its first argument. The expression on the right hand side must evaluate to a function, hence the `|...|...|` syntax generates a function with one argument.

    Example:

    `| Account.Order.Product | {'Price': Price * 1.2} |`

    defines a transform that will return a deep copy the object passed to it, but with the `Product` object modified such that its `Price` property has had its value increased by 20%. The first part of the expression is the path location that specifies all of the objects within the overall object to change, and the second part defines an object that will get merged into the object(s) matched by the first part. The merging semantics is the same as that of the `$merge()` function.

    This transform definition syntax creates a JSONata function which you can either assign to a variable and use multiple times, or invoke inline.
    Example:

    `payload ~> |Account.Order.Product|{'Price': Price * 1.2}|`

    or:

    `$increasePrice := |Account.Order.Product|{'Price': Price * 1.2}|`

    This also has the benefit that multiple transforms can be chained together for more complex transformations.

    In common with `$merge()`, multiple changes (inserts or updates) can be made to an object.
    Example:

    `|Account.Order.Product|{'Price': Price * 1.2, 'Total': Price * Quantity}|`

    Note that the Total will be calculated using the original price, not the modified one (JSONata is declarative not imperative).

    Properties can also be removed from objects. This is done using the optional `delete` clause which specifies the name(s) of the properties to delete.
    Example:

    `$ ~> |Account.Order.Product|{'Total': Price * Quantity}, ['Price', 'Quantity']|`

    This copies the input, but for each `Product` it inserts a Total and removes the `Price` and `Quantity` properties.

    # String functions

    ## `$string()`
    __Signature:__ `$string(arg, prettify)`

    Casts the `arg` parameter to a string using the following casting rules

    - Strings are unchanged
    - Functions are converted to an empty string
    - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number
    - All other values are converted to a JSON string using the [JSON.stringify](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) function

    If `arg` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `arg`.

    If `prettify` is true, then "prettified" JSON is produced. i.e One line per field and lines will be indented based on the field depth.

    __Examples__

    - `$string(5)` => `"5"`
    - `[1..5].$string()` => `["1", "2", "3", "4", "5"]`

    ## `$length()`
    __Signature:__ `$length(str)`

    Returns the number of characters in the string `str`. If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$length("Hello World")` => `11`

    ## `$substring()`
    __Signature:__ `$substring(str, start[, length])`

    Returns a string containing the characters in the first parameter `str` starting at position `start` (zero-offset). If `str` is not specified (i.e. this function is invoked with only the numeric argument(s)), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    If `length` is specified, then the substring will contain maximum `length` characters.

    If `start` is negative then it indicates the number of characters from the end of `str`. See [substr](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr) for full definition.

    __Examples__

    - `$substring("Hello World", 3)` => `"lo World"`
    - `$substring("Hello World", 3, 5)` => `"lo Wo"`
    - `$substring("Hello World", -4)` => `"orld"`
    - `$substring("Hello World", -4, 2)` => `"or"`

    ## `$substringBefore()`
    __Signature:__ `$substringBefore(str, chars)`

    Returns the substring before the first occurrence of the character sequence `chars` in `str`. If `str` is not specified (i.e. this function is invoked with only one argument), then the context value is used as the value of `str`. If `str` does not contain `chars`, then it returns `str`. An error is thrown if `str` and `chars` are not strings.

    __Examples__

    - `$substringBefore("Hello World", " ")` => `"Hello"`

    ## `$substringAfter()`
    __Signature:__ `$substringAfter(str, chars)`

    Returns the substring after the first occurrence of the character sequence `chars` in `str`. If `str` is not specified (i.e. this function is invoked with only one argument), then the context value is used as the value of `str`. If `str` does not contain `chars`, then it returns `str`. An error is thrown if `str` and `chars` are not strings.

    __Examples__

    - `$substringAfter("Hello World", " ")` => `"World"`


    ## `$uppercase()`
    __Signature:__ `$uppercase(str)`

    Returns a string with all the characters of `str` converted to uppercase. If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$uppercase("Hello World")` => `"HELLO WORLD"`


    ## `$lowercase()`
    __Signature:__ `$lowercase(str)`

    Returns a string with all the characters of `str` converted to lowercase. If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$lowercase("Hello World")` => `"hello world"`

    ## `$trim()`
    __Signature:__ `$trim(str)`

    Normalizes and trims all whitespace characters in `str` by applying the following steps:

    - All tabs, carriage returns, and line feeds are replaced with spaces.
    - Contiguous sequences of spaces are reduced to a single space.
    - Trailing and leading spaces are removed.

    If `str` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `str`. An error is thrown if `str` is not a string.

    __Examples__

    - `$trim(" Hello \n World ")` => `"Hello World"`


    ## `$pad()`
    __Signature:__ `$pad(str, width [, char])`

    Returns a copy of the string `str` with extra padding, if necessary, so that its total number of characters is at least the absolute value of the `width` parameter. If `width` is a positive number, then the string is padded to the right; if negative, it is padded to the left. The optional `char` argument specifies the padding character(s) to use. If not specified, it defaults to the space character.

    __Examples__

    - `$pad("foo", 5)` => `"foo "`
    - `$pad("foo", -5)` => `" foo"`
    - `$pad("foo", -5, "#")` => `"##foo"`
    - `$formatBase(35, 2) ~> $pad(-8, '0')` => `"00100011"`


    ## `$contains()`
    __Signature:__ `$contains(str, pattern)`

    Returns `true` if `str` is matched by `pattern`, otherwise it returns `false`. If `str` is not specified (i.e. this function is invoked with one argument), then the context value is used as the value of `str`.

    The `pattern` parameter can either be a string or a regular expression (regex). If it is a string, the function returns `true` if the characters within `pattern` are contained contiguously within `str`. If it is a regex, the function will return `true` if the regex matches the contents of `str`.

    __Examples__

    - `$contains("abracadabra", "bra")` => `true`
    - `$contains("abracadabra", /a.*a/)` => `true`
    - `$contains("abracadabra", /ar.*a/)` => `false`
    - `$contains("Hello World", /wo/)` => `false`
    - `$contains("Hello World", /wo/i)` => `true`
    - `Phone[$contains(number, /^077/)]` => `{ "type": "mobile", "number": "077 7700 1234" }`

    ## `$split()`
    __Signature:__ `$split(str, separator [, limit])`

    Splits the `str` parameter into an array of substrings. If `str` is not specified, then the context value is used as the value of `str`. It is an error if `str` is not a string.

    The `separator` parameter can either be a string or a regular expression (regex). If it is a string, it specifies the characters within `str` about which it should be split. If it is the empty string, `str` will be split into an array of single characters. If it is a regex, it splits the string around any sequence of characters that match the regex.

    The optional `limit` parameter is a number that specifies the maximum number of substrings to include in the resultant array. Any additional substrings are discarded. If `limit` is not specified, then `str` is fully split with no limit to the size of the resultant array. It is an error if `limit` is not a non-negative number.

    __Examples__

    - `$split("so many words", " ")` => `[ "so", "many", "words" ]`
    - `$split("so many words", " ", 2)` => `[ "so", "many" ]`
    - `$split("too much, punctuation. hard; to read", /[ ,.;]+/)` => `["too", "much", "punctuation", "hard", "to", "read"]`

    ## `$join()`
    __Signature:__ `$join(array[, separator])`

    Joins an array of component strings into a single concatenated string with each component string separated by the optional `separator` parameter.

    It is an error if the input array contains an item which isn't a string.

    If `separator` is not specified, then it is assumed to be the empty string, i.e. no separator between the component strings. It is an error if `separator` is not a string.

    __Examples__

    - `$join(['a','b','c'])` => `"abc"`
    - `$split("too much, punctuation. hard; to read", /[ ,.;]+/, 3) ~> $join(', ')` => `"too, much, punctuation"`

    ## `$match()`
    __Signature:__ `$match(str, pattern [, limit])`

    Applies the `str` string to the `pattern` regular expression and returns an array of objects, with each object containing information about each occurrence of a match withing `str`.

    The object contains the following fields:

    - `match` - the substring that was matched by the regex.
    - `index` - the offset (starting at zero) within `str` of this match.
    - `groups` - if the regex contains capturing groups (parentheses), this contains an array of strings representing each captured group.

    If `str` is not specified, then the context value is used as the value of `str`. It is an error if `str` is not a string.

    __Examples__

    `$match("ababbabbcc",/a(b+)/)` =>
    ```
    [
    {
    "match": "ab",
    "index": 0,
    "groups": ["b"]
    },
    {
    "match": "abb",
    "index": 2,
    "groups": ["bb"]
    },
    {
    "match": "abb",
    "index": 5,
    "groups": ["bb" ]
    }
    ]
    ```

    ## `$replace()`
    __Signature:__ `$replace(str, pattern, replacement [, limit])`

    Finds occurrences of `pattern` within `str` and replaces them with `replacement`.

    If `str` is not specified, then the context value is used as the value of `str`. It is an error if `str` is not a string.

    The `pattern` parameter can either be a string or a regular expression (regex). If it is a string, it specifies the substring(s) within `str` which should be replaced. If it is a regex, its is used to find .

    The `replacement` parameter can either be a string or a function. If it is a string, it specifies the sequence of characters that replace the substring(s) that are matched by `pattern`. If `pattern` is a regex, then the `replacement` string can refer to the characters that were matched by the regex as well as any of the captured groups using a `$` followed by a number `N`:

    - If `N = 0`, then it is replaced by substring matched by the regex as a whole.
    - If `N > 0`, then it is replaced by the substring captured by the Nth parenthesised group in the regex.
    - If `N` is greater than the number of captured groups, then it is replaced by the empty string.
    - A literal `$` character must be written as `$$` in the `replacement` string

    If the `replacement` parameter is a function, then it is invoked for each match occurrence of the `pattern` regex. The `replacement` function must take a single parameter which will be the object structure of a regex match as described in the `$match` function; and must return a string.

    The optional `limit` parameter, is a number that specifies the maximum number of replacements to make before stopping. The remainder of the input beyond this limit will be copied to the output unchanged.

    __Examples__


    **Query**
    ```
    $replace("John Smith and John Jones", "John", "Mr")
    ```
    **Result**
    ```
    "Mr Smith and Mr Jones"
    ```


    **Query**
    ```
    $replace("John Smith and John Jones", "John", "Mr", 1)
    ```
    **Result**
    ```
    "Mr Smith and John Jones"
    ```


    **Query**
    ```
    $replace("abracadabra", /a.*?a/, "*")
    ```
    **Result**
    ```
    "*c*bra"
    ```


    **Query**
    ```
    $replace("John Smith", /(\w+)\s(\w+)/, "$2, $1")
    ```
    **Result**
    ```
    "Smith, John"
    ```


    **Query**
    ```
    $replace("265USD", /([0-9]+)USD/, "$$$1")
    ```
    **Result**
    ```
    "$265"
    ```


    **Query**
    ```
    (
    $convert := function($m) {
    ($number($m.groups[0]) - 32) * 5/9 & "C"
    };
    $replace("temperature = 68F today", /(\d+)F/, $convert)
    )
    ```
    **Result**
    ```
    "temperature = 20C today"
    ```


    ## `$eval()`
    __Signature:__ `$eval(expr [, context])`

    Parses and evaluates the string `expr` which contains literal JSON or a JSONata expression using the current context as the context for evaluation.

    __Examples__


    **Query**
    ```
    $eval("[1,2,3]")
    ```
    **Result**
    ```
    [1, 2, 3]
    ```

    **Query**
    ```
    $eval('[1,$string(2),3]')
    ```
    **Result**
    ```
    [1,"2",3]
    ```


    Optionally override the context by specifying the second parameter

    ## `$base64encode()`
    __Signature:__ `$base64encode()`

    Converts an ASCII string to a base 64 representation. Each each character in the string is treated as a byte of binary data. This requires that all characters in the string are in the 0x00 to 0xFF range, which includes all characters in URI encoded strings. Unicode characters outside of that range are not supported.

    __Examples__

    - `$base64encode("myuser:mypass")` => `"bXl1c2VyOm15cGFzcw=="`


    ## `$base64decode()`
    __Signature:__ `$base64decode()`

    Converts base 64 encoded bytes to a string, using a UTF-8 Unicode codepage.

    __Examples__

    - `$base64decode("bXl1c2VyOm15cGFzcw==")` => `"myuser:mypass"`

    ## `$encodeUrlComponent()`
    __Signature:__ `$encodeUrlComponent(str)`

    Encodes a Uniform Resource Locator (URL) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.

    __Examples__

    - `$encodeUrlComponent("?x=test")` => `"%3Fx%3Dtest"`

    ## `$encodeUrl()`
    __Signature:__ `$encodeUrl(str)`

    Encodes a Uniform Resource Locator (URL) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.

    __Examples__

    - `$encodeUrl("https://mozilla.org/?x=шеллы")` => `"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"`

    ## `$decodeUrlComponent()`
    __Signature:__ `$decodeUrlComponent(str)`

    Decodes a Uniform Resource Locator (URL) component previously created by encodeUrlComponent.

    __Examples__

    - `$decodeUrlComponent("%3Fx%3Dtest")` => `"?x=test"`

    ## `$decodeUrl()`
    __Signature:__ `$decodeUrl(str)`

    Decodes a Uniform Resource Locator (URL) previously created by encodeUrl.

    __Examples__

    - `$decodeUrl("https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B")` => `"https://mozilla.org/?x=шеллы"`

    # Numeric functions

    ## `$number()`
    __Signature:__ `$number(arg)`

    Casts the `arg` parameter to a number using the following casting rules
    - Numbers are unchanged
    - Strings that contain a sequence of characters that represent a legal JSON number are converted to that number
    - Boolean `true` casts to `1`, Boolean `false` casts to `0`
    - All other values cause an error to be thrown.

    If `arg` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `arg`.

    __Examples__
    - `$number("5")` => `5`
    - `["1", "2", "3", "4", "5"].$number()` => `[1, 2, 3, 4, 5]`


    ## `$abs()`
    __Signature:__ `$abs(number)`

    Returns the absolute value of the `number` parameter, i.e. if the number is negative, it returns the positive value.

    If `number` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `number`.

    __Examples__
    - `$abs(5)` => `5`
    - `$abs(-5)` => `-5`

    ## `$floor()`
    __Signature:__ `$floor(number)`

    Returns the value of `number` rounded down to the nearest integer that is smaller or equal to `number`.

    If `number` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `number`.

    __Examples__
    - `$floor(5)` => `5`
    - `$floor(5.3)` => `5`
    - `$floor(5.8)` => `5`
    - `$floor(-5.3)` => `-6`


    ## `$ceil()`
    __Signature:__ `$ceil(number)`

    Returns the value of `number` rounded up to the nearest integer that is greater than or equal to `number`.

    If `number` is not specified (i.e. this function is invoked with no arguments), then the context value is used as the value of `number`.

    __Examples__
    - `$ceil(5)` => `5`
    - `$ceil(5.3)` => `6`
    - `$ceil(5.8)` => `6`
    - `$ceil(-5.3)` => `-5`


    ## `$round()`
    __Signature:__ `$round(number [, precision])`

    Returns the value of the `number` parameter rounded to the number of decimal places specified by the optional `precision` parameter.

    The `precision` parameter (which must be an integer) species the number of decimal places to be present in the rounded number. If `precision` is not specified then it defaults to the value `0` and the number is rounded to the nearest integer. If `precision` is negative, then its value specifies which column to round to on the left side of the decimal place

    This function uses the [Round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even) strategy to decide which way to round numbers that fall exactly between two candidates at the specified precision. This strategy is commonly used in financial calculations and is the default rounding mode in IEEE 754.

    __Examples__
    - `$round(123.456)` => `123`
    - `$round(123.456, 2)` => `123.46`
    - `$round(123.456, -1)` => `120`
    - `$round(123.456, -2)` => `100`
    - `$round(11.5)` => `12`
    - `$round(12.5)` => `12`
    - `$round(125, -1)` => `120`

    ## `$power()`
    __Signature:__ `$power(base, exponent)`

    Returns the value of `base` raised to the power of `exponent` (<code>base<sup>exponent</sup></code>).

    If `base` is not specified (i.e. this function is invoked with one argument), then the context value is used as the value of `base`.

    An error is thrown if the values of `base` and `exponent` lead to a value that cannot be represented as a JSON number (e.g. Infinity, complex numbers).

    __Examples__
    - `$power(2, 8)` => `256`
    - `$power(2, 0.5)` => `1.414213562373`
    - `$power(2, -2)` => `0.25`

    ## `$sqrt()`
    __Signature:__ `$sqrt(number)`

    Returns the square root of the value of the `number` parameter.

    If `number` is not specified (i.e. this function is invoked with one argument), then the context value is used as the value of `number`.

    An error is thrown if the value of `number` is negative.

    __Examples__
    - `$sqrt(4)` => `2`
    - `$sqrt(2)` => `1.414213562373`

    ## `$random()`
    __Signature:__ `$random()`

    Returns a pseudo random number greater than or equal to zero and less than one (<code>0 &#8804; n < 1</code>)

    __Examples__
    - `$random()` => `0.7973541067127`
    - `$random()` => `0.4029142127028`
    - `$random()` => `0.6558078550072`


    ## `$formatNumber()`
    __Signature:__ `$formatNumber(number, picture [, options])`

    Casts the `number` to a string and formats it to a decimal representation as specified by the `picture` string.

    The behaviour of this function is consistent with the XPath/XQuery function [fn:format-number](https://www.w3.org/TR/xpath-functions-31/#func-format-number) as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the number is formatted and has the [same syntax](https://www.w3.org/TR/xpath-functions-31/#syntax-of-picture-string) as fn:format-number.

    The optional third argument `options` is used to override the default locale specific formatting characters such as the decimal separator. If supplied, this argument must be an object containing name/value pairs specified in the [decimal format](https://www.w3.org/TR/xpath-functions-31/#defining-decimal-format) section of the XPath F&O 3.1 specification.

    __Examples__

    - `$formatNumber(12345.6, '#,###.00')` => `"12,345.60"`
    - `$formatNumber(1234.5678, "00.000e0")` => `"12.346e2"`
    - `$formatNumber(34.555, "#0.00;(#0.00)")` => `"34.56"`
    - `$formatNumber(-34.555, "#0.00;(#0.00)")` => `"(34.56)"`
    - `$formatNumber(0.14, "01%")` => `"14%"`
    - `$formatNumber(0.14, "###pm", {"per-mille": "pm"})` => `"140pm"`
    - `$formatNumber(1234.5678, "①①.①①①e①", {"zero-digit": "\u245f"})` => `"①②.③④⑥e②"`


    ## `$formatBase()`
    __Signature:__ `$formatBase(number [, radix])`

    Casts the `number` to a string and formats it to an integer represented in the number base specified by the `radix` argument. If `radix` is not specified, then it defaults to base 10. `radix` can be between 2 and 36, otherwise an error is thrown.

    __Examples__

    - `$formatBase(100, 2)` => `"1100100"`
    - `$formatBase(2555, 16)` => `"9fb"`


    ## `$formatInteger()`
    __Signature:__ `$formatInteger(number, picture)`

    Casts the `number` to a string and formats it to an integer representation as specified by the `picture` string.

    The behaviour of this function is consistent with the two-argument version of the XPath/XQuery function [fn:format-integer](https://www.w3.org/TR/xpath-functions-31/#func-format-integer) as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the number is formatted and has the same syntax as fn:format-integer.

    __Examples__

    - `$formatInteger(2789, 'w')` => `"two thousand, seven hundred and eighty-nine"`
    - `$formatInteger(1999, 'I')` => `"MCMXCIX"`

    ## `$parseInteger()`
    __Signature:__ `$parseInteger(string, picture)`

    Parses the contents of the `string` parameter to an integer (as a JSON number) using the format specified by the `picture` string.
    The picture string parameter has the same format as `$formatInteger`. Although the XPath specification does not have an equivalent
    function for parsing integers, this capability has been added to JSONata.

    __Examples__

    - `$parseInteger("twelve thousand, four hundred and seventy-six", 'w')` => `12476`
    - `$parseInteger('12,345,678', '#,##0')` => `12345678`

    # Numeric aggregation functions

    ## `$sum()`
    __Signature:__ `$sum(array)`

    Returns the arithmetic sum of an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$sum([5,1,3,7,4])` => `20`

    ## `$max()`
    __Signature:__ `$max(array)`

    Returns the maximum number in an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$max([5,1,3,7,4])` => `7`

    ## `$min()`
    __Signature:__ `$min(array)`

    Returns the minimum number in an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$min([5,1,3,7,4])` => `1`

    ## `$average()`
    __Signature:__ `$average(array)`

    Returns the mean value of an array of numbers. It is an error if the input array contains an item which isn't a number.

    __Example__

    - `$average([5,1,3,7,4])` => `4`

    # Boolean functions

    ## `$boolean()`
    __Signature:__ `$boolean(arg)`

    Casts the argument to a Boolean using the following rules:

    | Argument type | Result |
    | ------------- | ------ |
    | Boolean | unchanged |
    | string: empty | `false`|
    | string: non-empty | `true` |
    | number: 0 | `false`|
    | number: non-zero | `true` |
    | null | `false`|
    | array: empty | `false` |
    | array: contains a member that casts to `true` | `true` |
    | array: all members cast to `false` | `false` |
    | object: empty | `false` |
    | object: non-empty | `true` |
    | function | `false` |


    ## `$not()`
    __Signature:__ `$not(arg)`

    Returns Boolean NOT on the argument. `arg` is first cast to a boolean

    ## `$exists()`
    __Signature:__ `$exists(arg)`

    Returns Boolean `true` if the arg expression evaluates to a value, or `false` if the expression does not match anything (e.g. a path to a non-existent field reference).

    # Array Functions

    ## `$count()`
    __Signature:__ `$count(array)`

    Returns the number of items in the `array` parameter. If the `array` parameter is not an array, but rather a value of another JSON type, then the parameter is treated as a singleton array containing that value, and this function returns `1`.

    If `array` is not specified, then the context value is used as the value of `array`.

    __Examples__
    - `$count([1,2,3,1])` => `4`
    - `$count("hello")` => 1

    ## `$append()`
    __Signature:__ `$append(array1, array2)`

    Returns an array containing the values in `array1` followed by the values in `array2`. If either parameter is not an array, then it is treated as a singleton array containing that value.

    __Examples__
    - `$append([1,2,3], [4,5,6])` => `[1,2,3,4,5,6]`
    - `$append([1,2,3], 4)` => `[1,2,3,4]`
    - `$append("Hello", "World")` => `["Hello", "World"]`


    ## `$sort()`
    __Signature:__ `$sort(array [, function])`

    Returns an array containing all the values in the `array` parameter, but sorted into order. If no `function` parameter is supplied, then the `array` parameter must contain only numbers or only strings, and they will be sorted in order of increasing number, or increasing unicode codepoint respectively.

    If a comparator `function` is supplied, then is must be a function that takes two parameters:

    `function(left, right)`

    This function gets invoked by the sorting algorithm to compare two values `left` and `right`. If the value of `left` should be placed after the value of `right` in the desired sort order, then the function must return Boolean `true` to indicate a swap. Otherwise it must return `false`.

    __Example__
    ```
    $sort(Account.Order.Product, function($l, $r) {
    $l.Description.Weight > $r.Description.Weight
    })
    ```

    This sorts the products in order of increasing weight.

    The sorting algorithm is *stable* which means that values within the original array which are the same according to the comparator function will remain in the original order in the sorted array.

    ## `$reverse()`
    __Signature:__ `$reverse(array)`

    Returns an array containing all the values from the `array` parameter, but in reverse order.

    __Examples__
    - `$reverse(["Hello", "World"])` => `["World", "Hello"]`
    - `[1..5] ~> $reverse()` => `[5, 4, 3, 2, 1]`

    ## `$shuffle()`
    __Signature:__ `$shuffle(array)`

    Returns an array containing all the values from the `array` parameter, but shuffled into random order.

    __Examples__
    - `$shuffle([1..9])` => `[6, 8, 2, 3, 9, 5, 1, 4, 7]`

    ## `$distinct()`
    __Signature__ `$distinct(array)`

    Returns an array containing all the values from the `array` parameter, but with any duplicates removed. Values are tested for deep equality as if by using the [equality operator](#equals).

    __Examples__
    - `$distinct([1,2,3,3,4,3,5])` => `[1, 2, 3, 4, 5]`
    - `$distinct(Account.Order.Product.Description.Colour)` => `[ "Purple", "Orange", "Black" ]`

    ## `$zip()`
    __Signature:__ `$zip(array1, ...)`

    Returns a convolved (zipped) array containing grouped arrays of values from the `array1` ... `arrayN` arguments from index 0, 1, 2, etc.

    This function accepts a variable number of arguments. The length of the returned array is equal to the length of the shortest array in the arguments.

    __Examples__
    - `$zip([1,2,3], [4,5,6])` => `[[1,4] ,[2,5], [3,6]]`
    - `$zip([1,2,3],[4,5],[7,8,9])` => `[[1,4,7], [2,5,8]]`

    # Object functions

    ## `$keys()`
    __Signature:__ `$keys(object)`

    Returns an array containing the keys in the object. If the argument is an array of objects, then the array returned contains a de-duplicated list of all the keys in all of the objects.

    ## `$lookup()`
    __Signature:__ `$lookup(object, key)`

    Returns the value associated with `key` in `object`. If the first argument is an array of objects, then all of the objects in the array are searched, and the values associated with all occurrences of `key` are returned.


    ## `$spread()`
    __Signature:__ `$spread(object)`

    Splits an `object` containing key/value pairs into an array of objects, each of which has a single key/value pair from the input `object`. If the parameter is an array of objects, then the resultant array contains an object for every key/value pair in every object in the supplied array.

    ## `$merge()`
    __Signature:__ `$merge(array<object>)`

    Merges an array of objects into a single object containing all the key/value pairs from each of the objects in the input array. If any of the input objects contain the same key, then the returned object will contain the value of the last one in the array. It is an error if the input array contains an item that is not an object.

    ## `$sift()`
    __Signature:__ `$sift(object, function)`

    See definition under 'Higher-order functions'

    ## `$each()`
    __Signature:__ `$each(object, function)`

    Returns an array containing the values return by the `function` when applied to each key/value pair in the `object`.

    The `function` parameter will get invoked with two arguments:

    `function(value, name)`

    where the `value` parameter is the value of each name/value pair in the object and `name` is its name. The `name` parameter is optional.

    __Examples__

    `$each(Address, function($v, $k) {$k & ": " & $v})`

    =>

    [
    "Street: Hursley Park",
    "City: Winchester",
    "Postcode: SO21 2JN"
    ]

    ## `$error()`
    __Signature:__`$error(message)`

    Deliberately throws an error with an optional `message`

    ## `$assert()`
    __Signature:__`$assert(condition, message)`

    If condition is true, the function returns undefined. If the condition is false, an exception is thrown with the message as the message of the exception.

    ## `$type()`
    __Signature:__`$type(value)`

    Evaluates the type of `value` and returns one of the following strings:
    * `"null"`
    * `"number"`
    * `"string"`
    * `"boolean"`
    * `"array"`
    * `"object"`
    * `"function"`
    Returns (non-string) `undefined` when `value` is `undefined`.

    # Date/Time functions

    ## `$now()`
    __Signature:__ `$now([picture [, timezone]])`

    Generates a UTC timestamp in ISO 8601 compatible format and returns it as a string. All invocations of `$now()` within an evaluation of an expression will all return the same timestamp value.

    If the optional `picture` and `timezone` parameters are supplied, then the current timestamp is formatted as described by the [`$fromMillis()`](#frommillis) function.

    __Examples__

    - `$now()` => `"2017-05-15T15:12:59.152Z"`


    ## `$millis()`
    __Signature:__ `$millis()`

    Returns the number of milliseconds since the Unix *Epoch* (1 January, 1970 UTC) as a number. All invocations of `$millis()` within an evaluation of an expression will all return the same value.

    __Examples__
    - `$millis()` => `1502700297574`


    ## `$fromMillis()`
    __Signature:__ `$fromMillis(number [, picture [, timezone]])`

    Convert the `number` representing milliseconds since the Unix *Epoch* (1 January, 1970 UTC) to a formatted string representation of the timestamp as specified by the `picture` string.

    If the optional `picture` parameter is omitted, then the timestamp is formatted in the [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.

    If the optional `picture` string is supplied, then the timestamp is formatted occording to the representation specified in that string.
    The behaviour of this function is consistent with the two-argument version of the XPath/XQuery function [fn:format-dateTime](https://www.w3.org/TR/xpath-functions-31/#func-format-dateTime) as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the timestamp is formatted and has the [same syntax](https://www.w3.org/TR/xpath-functions-31/#date-picture-string) as fn:format-dateTime.

    If the optional `timezone` string is supplied, then the formatted timestamp will be in that timezone. The `timezone` string should be in the
    format "±HHMM", where ± is either the plus or minus sign and HHMM is the offset in hours and minutes from UTC. Positive offset for timezones
    east of UTC, negative offset for timezones west of UTC.

    __Examples__

    - `$fromMillis(1510067557121)` => `"2017-11-07T15:12:37.121Z"`
    - `$fromMillis(1510067557121, '[M01]/[D01]/[Y0001] [h#1]:[m01][P]')` => `"11/07/2017 3:12pm"`
    - `$fromMillis(1510067557121, '[H01]:[m01]:[s01] [z]', '-0500')` => `"10:12:37 GMT-05:00"`

    ## `$toMillis()`
    __Signature:__ `$toMillis(timestamp [, picture])`

    Convert a `timestamp` string to the number of milliseconds since the Unix *Epoch* (1 January, 1970 UTC) as a number.

    If the optional `picture` string is not specified, then the format of the timestamp is assumed to be [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). An error is thrown if the string is not in the correct format.

    If the `picture` string is specified, then the format is assumed to be described by this picture string using the [same syntax](https://www.w3.org/TR/xpath-functions-31/#date-picture-string) as the XPath/XQuery function [fn:format-dateTime](https://www.w3.org/TR/xpath-functions-31/#func-format-dateTime), defined in the XPath F&O 3.1 specification.

    __Examples__

    - `$toMillis("2017-11-07T15:07:54.972Z")` => `1510067274972`

    # Higher order functions

    ## `$map()`
    __Signature:__ `$map(array, function)`

    Returns an array containing the results of applying the `function` parameter to each value in the `array` parameter.

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, index [, array]])`

    Each value in the input array is passed in as the first parameter in the supplied function. The index (position) of that value in the input array is passed in as the second parameter, if specified. The whole input array is passed in as the third parameter, if specified.

    __Examples__
    - `$map([1..5], $string)` => `["1", "2", "3", "4", "5"]`

    With user-defined (lambda) function:
    ```
    $map(Email.address, function($v, $i, $a) {
    'Item ' & ($i+1) & ' of ' & $count($a) & ': ' & $v
    })
    ```

    evaluates to:

    ```
    [
    "Item 1 of 4: fred.smith@my-work.com",
    "Item 2 of 4: fsmith@my-work.com",
    "Item 3 of 4: freddy@my-social.com",
    "Item 4 of 4: frederic.smith@very-serious.com"
    ]
    ```

    ## `$filter()`
    __Signature:__ `$filter(array, function)`

    Returns an array containing only the values in the `array` parameter that satisfy the `function` predicate (i.e. `function` returns Boolean `true` when passed the value).

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, index [, array]])`

    Each value in the input array is passed in as the first parameter in the supplied function. The index (position) of that value in the input array is passed in as the second parameter, if specified. The whole input array is passed in as the third parameter, if specified.

    __Example__
    The following expression returns all the products whose price is higher than average:
    ```
    $filter(Account.Order.Product, function($v, $i, $a) {
    $v.Price > $average($a.Price)
    })
    ```

    ## `$single()`
    __Signature:__ `$single(array, function)`

    Returns the one and only one value in the `array` parameter that satisfy the `function` predicate (i.e. `function` returns Boolean `true` when passed the value). Throws an exception if the number of matching values is not exactly one.

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, index [, array]])`

    Each value in the input array is passed in as the first parameter in the supplied function. The index (position) of that value in the input array is passed in as the second parameter, if specified. The whole input array is passed in as the third parameter, if specified.

    __Example__
    The following expression the product in the order whose SKU is `"0406654608"`:
    ```
    $single(Account.Order.Product, function($v, $i, $a) {
    $v.SKU = "0406654608"
    })
    ```

    ## `$reduce()`
    __Signature:__ `$reduce(array, function [, init])`

    Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.

    The `function` must accept at least two arguments, and behaves like an infix operator between each value within the `array`. The signature of this supplied function must be of the form:

    `myfunc($accumulator, $value[, $index[, $array]])`

    __Example__

    ```
    (
    $product := function($i, $j){$i * $j};
    $reduce([1..5], $product)
    )
    ```

    This multiplies all the values together in the array `[1..5]` to return `120`.

    If the optional `init` parameter is supplied, then that value is used as the initial value in the aggregation (fold) process. If not supplied, the initial value is the first value in the `array` parameter.

    ## `$sift()`
    __Signature:__ `$sift(object, function)`

    Returns an object that contains only the key/value pairs from the `object` parameter that satisfy the predicate `function` passed in as the second parameter.

    If `object` is not specified, then the context value is used as the value of `object`. It is an error if `object` is not an object.

    The function that is supplied as the second parameter must have the following signature:

    `function(value [, key [, object]])`

    Each value in the input object is passed in as the first parameter in the supplied function. The key (property name) of that value in the input object is passed in as the second parameter, if specified. The whole input object is passed in as the third parameter, if specified.

    __Example__

    ```
    Account.Order.Product.$sift(function($v, $k) {$k ~> /^Product/})
    ```

    This sifts each of the `Product` objects such that they only contain the fields whose keys start with the string "Product" (using a regex). This example returns:

    ```
    [
    {
    "Product Name": "Bowler Hat",
    "ProductID": 858383
    },
    {
    "Product Name": "Trilby hat",
    "ProductID": 858236
    },
    {
    "Product Name": "Bowler Hat",
    "ProductID": 858383
    },
    {
    "ProductID": 345664,
    "Product Name": "Cloak"
    }
    ]
    ```
    \ No newline at end of file diff --git a/data_science/python/index.html b/data_science/python/index.html index 3e219c613d..06e446845e 100644 --- a/data_science/python/index.html +++ b/data_science/python/index.html @@ -10,8 +10,8 @@ - - + +

    Preparing to Analyze Your Data in Python

    @@ -48,6 +48,6 @@

    Qu
    LAMP.ActivityEvent.all_by_participant(participant_1)['data'][0]
    # {'timestamp': 1600557560000,
    # 'duration': 15000,
    # 'activity': '16fnz109gs4sehyfc84n',
    # 'static_data': {},
    # 'temporal_slices': [{'item': 'How did you feel this week?',
    # 'value': 'Okay',
    # 'type': 'valid',
    # 'duration': 5000,
    # 'level': None},
    # {'item': 'Have you been admitted to the hospital for psychiatric reasons in the past week?',
    # 'value': 'No',
    # 'type': 'valid',
    # 'duration': 7000,
    # 'level': None},
    # {'item': 'Use this space to write down your thoughts and feelings about the week. ',
    # 'value': 'it was okay',
    # 'type': 'valid',
    # 'duration': 3000,
    # 'level': None}]}

    Details of the 'activity can be be viewed the following method

    -
    LAMP.Activity.view('16fnz109gs4sehyfc84n')

    +
    LAMP.Activity.view('16fnz109gs4sehyfc84n')
    \ No newline at end of file diff --git a/data_science/r/index.html b/data_science/r/index.html index 2bd426b443..8c87d70182 100644 --- a/data_science/r/index.html +++ b/data_science/r/index.html @@ -10,8 +10,8 @@ - - + +

    Preparing to Analyze Your Data in R

    @@ -75,6 +75,6 @@

    fit <- lm(average_PIU ~ average_GAD, data = drop_na(data))

    Plot the now-filtered data; you’ll find our sample graph below. (drop_na() removes rows with one or more NA values.)

    ggplot(drop_na(data), aes(x = average_GAD, y = average_PIU)) +
    geom_point() +
    geom_smooth(method = 'lm', formula = y~x) +
    # From https://sejohnston.com/2012/08/09/a-quick-and-easy-function-to-plot-lm-results-in-r/
    labs(title = paste("Adj R2 = ",signif(summary(fit)$adj.r.squared, 5),
    "Intercept =",signif(fit$coef[[1]],5 ),
    " Slope =",signif(fit$coef[[2]], 5),
    " P =",signif(summary(fit)$coef[2,4], 5)),
    x = "Average GAD-7",
    y = "Average PIU-SF-6") +
    theme_minimal(base_size = 12) +
    theme(
    panel.grid.major = element_blank(),
    panel.background = element_blank(),
    axis.line = element_line(colour = "black"),
    axis.title.x = element_text(size = 12))
    -

    +

    \ No newline at end of file diff --git a/data_science/tags/index.html b/data_science/tags/index.html index 4c5961a5b5..49e9cd4573 100644 --- a/data_science/tags/index.html +++ b/data_science/tags/index.html @@ -10,8 +10,8 @@ - - + +

    Tags & Attachments

    @@ -50,6 +50,6 @@

    Case Example 2: Removing a conflict

    In the following code block, both "ffmz65mn1gtav5fq3bhq" (a Researcher), and 'dynp0g0530xkahnzh0xc' (a Study) attempt to set the lamp.test tag on the user 'U0591253803'. As before, since the Researcher has a higher authority than the Study, the tag set by the Researcher is returned (even though the tag set by the Study was set later).

    However, the Researcher tag is then removed, and the tag set by the Study is now the one returned by the API

    -
    LAMP.Type.set_attachment("ffmz65mn1gtav5fq3bhq",'U0591253803','lamp.test','Set by Researcher')['data']
    LAMP.Type.set_attachment('dynp0g0530xkahnzh0xc','U0591253803','lamp.test','Set by Study')['data']

    LAMP.Type.get_attachment('U0591253803', 'lamp.test')['data']
    'Set by Researcher'

    LAMP.Type.set_attachment("ffmz65mn1gtav5fq3bhq",'U0591253803','lamp.test',None)['data']

    LAMP.Type.get_attachment('U0591253803', 'lamp.test')['data']
    'Set by Study'
    +
    LAMP.Type.set_attachment("ffmz65mn1gtav5fq3bhq",'U0591253803','lamp.test','Set by Researcher')['data']
    LAMP.Type.set_attachment('dynp0g0530xkahnzh0xc','U0591253803','lamp.test','Set by Study')['data']

    LAMP.Type.get_attachment('U0591253803', 'lamp.test')['data']
    'Set by Researcher'

    LAMP.Type.set_attachment("ffmz65mn1gtav5fq3bhq",'U0591253803','lamp.test',None)['data']

    LAMP.Type.get_attachment('U0591253803', 'lamp.test')['data']
    'Set by Study'
    \ No newline at end of file diff --git a/deploy/aws/index.html b/deploy/aws/index.html index d4219ea496..01c063bcb6 100644 --- a/deploy/aws/index.html +++ b/deploy/aws/index.html @@ -10,8 +10,8 @@ - - + + +

    We are working closely with Amazon Web Services (AWS) to bring this feature to all organizations using the LAMP Platform. If you or your organization are interested, please contact us.

    \ No newline at end of file diff --git a/deploy/cloudformation/index.html b/deploy/cloudformation/index.html index b6a533e54f..cd37cc38ac 100644 --- a/deploy/cloudformation/index.html +++ b/deploy/cloudformation/index.html @@ -10,8 +10,8 @@ - - + +

    Deploying via CloudFormation

    @@ -23,6 +23,6 @@

    CreateUpdate

    aws cloudformation update-stack \
    --region us-east-2 \
    --stack-name LAMP \
    --template-body file://cloudformation.yaml \
    --capabilities CAPABILITY_NAMED_IAM \
    --parameters HostedZoneId=YOUR_HOSTED_ZONE_HERE,DomainName=YOUR_DOMAIN_NAME_HERE,InstanceType=t3.medium,ImageId=ami-0f57b4cec24530068,VpcCidrBlock=10.0.0.0/16,SubnetCidrBlock=10.0.0.0/24,KeyName=YOUR_KEY_NAME_HERE,SecurityGroupName=mindLAMP-platform-ec2-sg,SshCidrBlock=52.95.4.0/24,Ec2Instance01Name=mindLAMP-platform-ec2-01,Ec2Instance02Name=mindLAMP-platform-ec2-02

    Delete

    -
    aws cloudformation delete-stack \
    --region us-east-2 \
    --stack-name LAMP
    +
    aws cloudformation delete-stack \
    --region us-east-2 \
    --stack-name LAMP
    \ No newline at end of file diff --git a/deploy/configure_oauth_google/index.html b/deploy/configure_oauth_google/index.html index c1600a0454..14e2003865 100644 --- a/deploy/configure_oauth_google/index.html +++ b/deploy/configure_oauth_google/index.html @@ -10,8 +10,8 @@ - - + + +

    Remember that OAUTH_REDIRECT_URI must be exactly the same as the redirect URI the client was set up with.

    \ No newline at end of file diff --git a/deploy/costs/index.html b/deploy/costs/index.html index 803b5d441c..2513788ffd 100644 --- a/deploy/costs/index.html +++ b/deploy/costs/index.html @@ -10,8 +10,8 @@ - - + +

    Costs of Deploying the LAMP Platform

    @@ -56,6 +56,6 @@

    Please reach out to us for a consultation if you or your organization would like assistance with self-hosting.

    Though self-hosting may appear to be cheaper, the "hidden costs" should not be neglected in: ensuring redundant storage, no system down-time, regular storage backups, HIPAA-compatible encryption during flight and at rest, preventing network bottlenecks, regular system maintenance, and more.

    -

    We do not recommend self-hosting unless your organization already has the infrastructure to correctly do so.

    +

    We do not recommend self-hosting unless your organization already has the infrastructure to correctly do so.

    \ No newline at end of file diff --git a/deploy/deploying/index.html b/deploy/deploying/index.html index cdee9b3963..50d80761c4 100644 --- a/deploy/deploying/index.html +++ b/deploy/deploying/index.html @@ -10,8 +10,8 @@ - - + +

    Deploying the LAMP Platform

    @@ -101,6 +101,6 @@

    LAMP Platform<
    docker stack deploy --compose-file lamp.yml lamp

    Maintaining and Updating the LAMP Platform

    If you are using this Docker Stack provided, you will only need to run a docker service update command on the API Server to pull the latest image. Because Docker image versioning is calendar-based, at the moment you will manually need to update from 2022 to 2023, and so on.

    -

    If you are deploying multiple LAMP stacks, please ensure the traefik router rules have been renamed! (i.e. Ensure traefik.http.routers.lamp_dashboard.rule and traefik.http.routers.lamp_dashboard_2.rule are distinct.) If two or more instances of the same rule exist, the router will overwrite the first instance.

    +

    If you are deploying multiple LAMP stacks, please ensure the traefik router rules have been renamed! (i.e. Ensure traefik.http.routers.lamp_dashboard.rule and traefik.http.routers.lamp_dashboard_2.rule are distinct.) If two or more instances of the same rule exist, the router will overwrite the first instance.

    \ No newline at end of file diff --git a/deploy/enabling_sensors_and_activities/index.html b/deploy/enabling_sensors_and_activities/index.html index 64adc64492..073c6f0fe7 100644 --- a/deploy/enabling_sensors_and_activities/index.html +++ b/deploy/enabling_sensors_and_activities/index.html @@ -10,8 +10,8 @@ - - + +

    Configuring your server to add Sensors and Activities

    @@ -35,6 +35,6 @@
  • Select "execute". Check back in the dashboard for an updated dropdown list!
  • Automated Script

    -
    import LAMP

    ACTIVITY_SPEC_LIST = [
    "lamp.spatial_span",
    "lamp.cats_and_dogs",
    "lamp.jewels_a",
    "lamp.jewels_b",
    "lamp.dbt_diary_card",
    "lamp.balloon_risk",
    "lamp.pop_the_bubbles",
    "lamp.journal",
    "lamp.breathe",
    "lamp.recording",
    "lamp.survey",
    "lamp.scratch_image",
    "lamp.tips",
    "lamp.goals",
    "lamp.medications",
    "lamp.memory_game",
    "lamp.spin_wheel",
    "lamp.maze_game",
    "lamp.emotion_recognition",
    "lamp.symbol_digit_substitution"
    ]

    SENSOR_SPEC_LIST = [
    "lamp.accelerometer",
    "lamp.accelerometer.motion",
    "lamp.analytics",
    "lamp.blood_pressure",
    "lamp.bluetooth",
    "lamp.calls",
    "lamp.device_state",
    "lamp.distance",
    "lamp.flights",
    "lamp.gps",
    "lamp.gps.contextual",
    "lamp.gyroscope",
    "lamp.heart_rate",
    "lamp.height",
    "lamp.magnetometer",
    "lamp.respiratory_rate",
    "lamp.segment",
    "lamp.sleep",
    "lamp.sms",
    "lamp.steps",
    "lamp.weight",
    "lamp.wifi",
    ]

    print("[LAMP Platform] ActivitySpec & SensorSpec Initialization Tool")
    print("You must enter your username, password, and server address to continue installation.")
    print("Username: admin [CANNOT BE CHANGED]")
    LAMP.connect("admin", input("Password: "), input("Server Address: "))

    for spec in ACTIVITY_SPEC_LIST:
    print(f"Creating ActivitySpec '{spec}'...")
    LAMP.ActivitySpec.create({ "name": spec })
    for spec in SENSOR_SPEC_LIST:
    print(f"Creating SensorSpec '{spec}'...")
    LAMP.SensorSpec.create({ "name": spec })
    +
    import LAMP

    ACTIVITY_SPEC_LIST = [
    "lamp.spatial_span",
    "lamp.cats_and_dogs",
    "lamp.jewels_a",
    "lamp.jewels_b",
    "lamp.dbt_diary_card",
    "lamp.balloon_risk",
    "lamp.pop_the_bubbles",
    "lamp.journal",
    "lamp.breathe",
    "lamp.recording",
    "lamp.survey",
    "lamp.scratch_image",
    "lamp.tips",
    "lamp.goals",
    "lamp.medications",
    "lamp.memory_game",
    "lamp.spin_wheel",
    "lamp.maze_game",
    "lamp.emotion_recognition",
    "lamp.symbol_digit_substitution"
    ]

    SENSOR_SPEC_LIST = [
    "lamp.accelerometer",
    "lamp.accelerometer.motion",
    "lamp.analytics",
    "lamp.blood_pressure",
    "lamp.bluetooth",
    "lamp.calls",
    "lamp.device_state",
    "lamp.distance",
    "lamp.flights",
    "lamp.gps",
    "lamp.gps.contextual",
    "lamp.gyroscope",
    "lamp.heart_rate",
    "lamp.height",
    "lamp.magnetometer",
    "lamp.respiratory_rate",
    "lamp.segment",
    "lamp.sleep",
    "lamp.sms",
    "lamp.steps",
    "lamp.weight",
    "lamp.wifi",
    ]

    print("[LAMP Platform] ActivitySpec & SensorSpec Initialization Tool")
    print("You must enter your username, password, and server address to continue installation.")
    print("Username: admin [CANNOT BE CHANGED]")
    LAMP.connect("admin", input("Password: "), input("Server Address: "))

    for spec in ACTIVITY_SPEC_LIST:
    print(f"Creating ActivitySpec '{spec}'...")
    LAMP.ActivitySpec.create({ "name": spec })
    for spec in SENSOR_SPEC_LIST:
    print(f"Creating SensorSpec '{spec}'...")
    LAMP.SensorSpec.create({ "name": spec })
    \ No newline at end of file diff --git a/deploy/passwords/index.html b/deploy/passwords/index.html index edfcfefa1a..e9fa215545 100644 --- a/deploy/passwords/index.html +++ b/deploy/passwords/index.html @@ -10,8 +10,8 @@ - - + +
    +
    caution

    Upon initially creating a user account, user password will be automatically generated in the default format, regardless of password rules. I.e. a user given the account U1338759043@lamp.com will automatically be given the password U1338759043 regardless of password complexity settings.

    \ No newline at end of file diff --git a/deploy/prereqs/index.html b/deploy/prereqs/index.html index 1076ce8761..36507e712c 100644 --- a/deploy/prereqs/index.html +++ b/deploy/prereqs/index.html @@ -10,8 +10,8 @@ - - + +

    Prerequisites for Deploying the LAMP Platform

    @@ -95,6 +95,6 @@

    Options: You can use the existing mindLAMP Native App submitted by the Division of Digital Psychiatry and vetted by Apple and Google with your customized Frontend or Backend.


    It is always possible to customize the activities and sensors your patients will see in the app using the standard frontend hosted by BIDMC. You do not need to self-host the frontend.

    -

    Even if your organization chooses to make modifications to any of these components when self-deploying them, they remain compatible with one-another. For example, if one organization self-deploys a new Frontend user experience or adds medical devices support to the Native App, it remains compatible with another organization's self-deployed Backend.

    +

    Even if your organization chooses to make modifications to any of these components when self-deploying them, they remain compatible with one-another. For example, if one organization self-deploys a new Frontend user experience or adds medical devices support to the Native App, it remains compatible with another organization's self-deployed Backend.

    \ No newline at end of file diff --git a/deploy/provisioning/index.html b/deploy/provisioning/index.html index 94ec71a083..06f239967b 100644 --- a/deploy/provisioning/index.html +++ b/deploy/provisioning/index.html @@ -10,8 +10,8 @@ - - + +

    Provisioning the LAMP Platform

    @@ -28,6 +28,6 @@

    When developing or testing the LAMP Platform, it is useful and effective to segment compute resources and develop natively in the cloud (or on-prem). Consider carefully how your organization expects to the use the LAMP Platform and segregate computing resources (nodes) to reduce cost and improve performance.

    The LAMP Platform source code repositories are hosted on GitHub and use the GitHub Actions and GitHub Packages features to quickly perform continuous testing, integration, and deployment. As code is pull requested from a feature branch into the master branch, it should pass a round of code review and pass any/all unit tests. Once the code is merged, the automated CI/CD will prepare and upload Docker images.

    We highly recommend the use of Portainer to remotely manage your Docker Swarm nodes and container health, as well as Traefik for managing service mesh routing and in-flight TLS encryption; additional Docker Stack files and instructions are provided for both. The Traefik router interfaces with Docker Swarm and your DNS provider to automatically manage internal and external access to services, according to the configuration in the Docker Stack files provided. To monitor node health and container resource metrics, we recommend Netdata and have included it in the stack file below.

    -

    If you'd like to follow along but would like to test the deployment out first, or don't have provisioned resources yet, consider using Play With Docker, a free service from the Docker team where you can provision a temporary Swarm cluster.

    +

    If you'd like to follow along but would like to test the deployment out first, or don't have provisioned resources yet, consider using Play With Docker, a free service from the Docker team where you can provision a temporary Swarm cluster.

    \ No newline at end of file diff --git a/deploy/recs/index.html b/deploy/recs/index.html index 8255a6703d..5272496e63 100644 --- a/deploy/recs/index.html +++ b/deploy/recs/index.html @@ -10,8 +10,8 @@ - - + +

    Deployment Recommendations

    @@ -22,6 +22,6 @@

    Technical Requirements

    The use of Docker is imperative to successful self-deployment. A single Docker Stack file is used to automate single-node or multi-node deployments, and requires Docker Swarm (multi-node for cloud testing, integration, and production usage, or single-node for local testing or smaller deployments). The LAMP Platform has only been tested with Docker Swarm, so therefore our team is only equipped to provide support for those using Docker or Docker compatible services.

    We highly recommend the use of Portainer as a Swarm Management Console to make it easier to troubleshoot failed deployments, rapidly test and integrate new components, and effectively monitor container logs and health. Read this documentation to learn more about Portainer and how to configure and use it. We also recommend Traefik for managing service mesh routing and in-flight TLS encryption; additional Docker Stack files and instructions are provided for both in the self-deploy documentation.

    Remote Access (WAF) Notes

    -

    The mobile apps and browsers must make an initial connection to the hosted VersionCheck API (part of the App Gateway) before downloading the user interface component. If your organization chooses to submit separate copies of the mobile apps to the Apple/Google app stores, you will also be responsible for deploying the App Gateway within your organization as well. This also means your organization must "pin" the versions of components as accessed from the VersionCheck API. If your organization is NOT deploying an internal App Gateway (i.e if using the existing mindLAMP apps on the App Store) then you will be using the App Gateway as hosted by the Division of Digital Psychiatry. (This must be disclosed in security/IT diagrams.)

    +

    The mobile apps and browsers must make an initial connection to the hosted VersionCheck API (part of the App Gateway) before downloading the user interface component. If your organization chooses to submit separate copies of the mobile apps to the Apple/Google app stores, you will also be responsible for deploying the App Gateway within your organization as well. This also means your organization must "pin" the versions of components as accessed from the VersionCheck API. If your organization is NOT deploying an internal App Gateway (i.e if using the existing mindLAMP apps on the App Store) then you will be using the App Gateway as hosted by the Division of Digital Psychiatry. (This must be disclosed in security/IT diagrams.)

    \ No newline at end of file diff --git a/deploy/testing/index.html b/deploy/testing/index.html index e68d01af60..f4bca4f843 100644 --- a/deploy/testing/index.html +++ b/deploy/testing/index.html @@ -10,8 +10,8 @@ - - + +

    Testing the LAMP Platform

    @@ -46,6 +46,6 @@

    If any of the above steps fails to complete successfully you will not be able to reach this step.

    Password encrypt/decryption script

    If you need to manually encrypt/decrypt your secret key, see the below script. You can execute this script via terminal with node <script_name> <encrypt:decrypt> <secret_key>. Please replace <ROOT_KEY> with the root key used in your lamp-server service.

    -
    #!/usr/bin/env node
    const PRIVATE_KEY = <ROOT_KEY> // DO NOT SHARE!

    const crypto = require('crypto')
    const mode = (process.argv[2] || '')
    const input = (process.argv[3] || '')
    let output = 'Usage: passcrypt.js <encrypt | decrypt> <string to encrypt or decrypt>'

    try {
    if (mode === 'encrypt') {
    let ivl = crypto.randomBytes(16)
    let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(PRIVATE_KEY, 'hex'), ivl)
    output = Buffer.concat([
    ivl,
    cipher.update(Buffer.from(input, 'utf16le')),
    cipher.final()
    ]).toString('base64')
    } else if (mode === 'decrypt') {
    let dat = Buffer.from(input, 'base64')
    let cipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(PRIVATE_KEY, 'hex'), dat.slice(0, 16))
    output = Buffer.concat([
    cipher.update(dat.slice(16)),
    cipher.final()
    ]).toString('utf16le')
    }
    console.dir(output)
    } catch(e) {
    console.log('*** ERROR: Could not ' + mode + ' the string. ***')
    process.exit(1)
    }
    +
    #!/usr/bin/env node
    const PRIVATE_KEY = <ROOT_KEY> // DO NOT SHARE!

    const crypto = require('crypto')
    const mode = (process.argv[2] || '')
    const input = (process.argv[3] || '')
    let output = 'Usage: passcrypt.js <encrypt | decrypt> <string to encrypt or decrypt>'

    try {
    if (mode === 'encrypt') {
    let ivl = crypto.randomBytes(16)
    let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(PRIVATE_KEY, 'hex'), ivl)
    output = Buffer.concat([
    ivl,
    cipher.update(Buffer.from(input, 'utf16le')),
    cipher.final()
    ]).toString('base64')
    } else if (mode === 'decrypt') {
    let dat = Buffer.from(input, 'base64')
    let cipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(PRIVATE_KEY, 'hex'), dat.slice(0, 16))
    output = Buffer.concat([
    cipher.update(dat.slice(16)),
    cipher.final()
    ]).toString('utf16le')
    }
    console.dir(output)
    } catch(e) {
    console.log('*** ERROR: Could not ' + mode + ' the string. ***')
    process.exit(1)
    }
    \ No newline at end of file diff --git a/deploy/troubleshooting/index.html b/deploy/troubleshooting/index.html index 1dac7f0281..9d1e2677b1 100644 --- a/deploy/troubleshooting/index.html +++ b/deploy/troubleshooting/index.html @@ -10,8 +10,8 @@ - - + +
    +
        logging:
    options:
    max-size: "10m"
    max-file: "3"
    \ No newline at end of file diff --git a/develop/Repositories/creating-github-release/index.html b/develop/Repositories/creating-github-release/index.html index 8b224b8a19..b0b19b562a 100644 --- a/develop/Repositories/creating-github-release/index.html +++ b/develop/Repositories/creating-github-release/index.html @@ -10,8 +10,8 @@ - - + + +

    \ No newline at end of file diff --git a/develop/Repositories/writing-documentation/index.html b/develop/Repositories/writing-documentation/index.html index 0e7eed35ff..985a43c11c 100644 --- a/develop/Repositories/writing-documentation/index.html +++ b/develop/Repositories/writing-documentation/index.html @@ -10,8 +10,8 @@ - - + + +

    The new documentation should then appear in docs.lamp.digital

    \ No newline at end of file diff --git a/develop/Training Modules/training-modules/index.html b/develop/Training Modules/training-modules/index.html index 5df1d5c0df..1564e7f1c3 100644 --- a/develop/Training Modules/training-modules/index.html +++ b/develop/Training Modules/training-modules/index.html @@ -10,8 +10,8 @@ - - + +

    Training Modules

    @@ -1081,6 +1081,6 @@

    Markdown

    Backend: content patients cannot see. This includes anything on the server.

    Instructions below on how to make a warning sign (for more information, navigate to https://docusaurus.io/docs/markdown-features/admonitions):

    Danger sign syntax:

    -
    danger

    [insert the message]

    +
    danger

    [insert the message]

    \ No newline at end of file diff --git a/develop/adaptive_interventions/index.html b/develop/adaptive_interventions/index.html index 2d2854510c..56c2ecca26 100644 --- a/develop/adaptive_interventions/index.html +++ b/develop/adaptive_interventions/index.html @@ -10,8 +10,8 @@ - - + +

    Just-In-Time Adaptive Interventions

    @@ -77,6 +77,6 @@

    Pri
  • lamp.messaging Tag: This added backwards-compatible support for the Conversations feature of the dashboard.
  • lamp.dashboard.welcome_dismissed Tag: Unknown; this Tag was never used.
  • lamp.selectedStudies, lamp.selectedActivities, and lamp.selectedSensors Tags: Due to bugs in the earliest version of the mindLAMP v2 dashboard, these tags held an array of studies, activities, or sensors that were selected by the currently logged in Researcher. This is now defunct and should not be used (localStorage should be used instead).
  • -

    +
    \ No newline at end of file diff --git a/develop/app_gateway/index.html b/develop/app_gateway/index.html index 0110f422fe..a52333926d 100644 --- a/develop/app_gateway/index.html +++ b/develop/app_gateway/index.html @@ -10,8 +10,8 @@ - - + + +

    \ No newline at end of file diff --git a/develop/build_new_activities/index.html b/develop/build_new_activities/index.html index 6e8ed979ed..416023348b 100644 --- a/develop/build_new_activities/index.html +++ b/develop/build_new_activities/index.html @@ -10,8 +10,8 @@ - - + +

    Building New Activities

    @@ -37,6 +37,6 @@

    Initialized Settings from LAMP

    Using the settings we added to the document, we can access these variables using the addEventListener()

    -
    window.addEventListener("message", (event) => {
    // console.log(event)
    settings = event.data.activity.settings

    totalTrials = settings.totalTrials // the totalTrials settings can be accessed here

    totalTrials = 20 //default
    maxTime = settings.maxTime // the maxTime settings can be accessed here


    }, false);
    +
    window.addEventListener("message", (event) => {
    // console.log(event)
    settings = event.data.activity.settings

    totalTrials = settings.totalTrials // the totalTrials settings can be accessed here

    totalTrials = 20 //default
    maxTime = settings.maxTime // the maxTime settings can be accessed here


    }, false);
    \ No newline at end of file diff --git a/develop/couchdb-migration/index.html b/develop/couchdb-migration/index.html index 1f74dfcb7f..f13068169a 100644 --- a/develop/couchdb-migration/index.html +++ b/develop/couchdb-migration/index.html @@ -10,8 +10,8 @@ - - + +

    Migrating from CouchDB to MongoDB

    @@ -20,6 +20,6 @@

    You will likely need to adjust Node options to run the script.

    export node_options=--max_old_space_size=14000
    # set to around ~80% of max limit (default of 2GB WILL FAIL)

    To automate installation of prerequisite packages, use this package.json:

    -
    package.json
    {
    "name": "couch_mongo_importer",
    "version": "1.0.0",
    "main": "index.js",
    "scripts": {
    "start": "node index.js"
    },
    "dependencies": {
    "event-stream": "^4.0.1",
    "JSONStream": "^1.3.5",
    "mongodb": "^3.6.6",
    "nano": "^9.0.3",
    "through2-batch": "^1.1.1"
    }
    }
    +
    package.json
    {
    "name": "couch_mongo_importer",
    "version": "1.0.0",
    "main": "index.js",
    "scripts": {
    "start": "node index.js"
    },
    "dependencies": {
    "event-stream": "^4.0.1",
    "JSONStream": "^1.3.5",
    "mongodb": "^3.6.6",
    "nano": "^9.0.3",
    "through2-batch": "^1.1.1"
    }
    }
    \ No newline at end of file diff --git a/develop/cron_jobs/index.html b/develop/cron_jobs/index.html index a0f42a4c65..d56acbae77 100644 --- a/develop/cron_jobs/index.html +++ b/develop/cron_jobs/index.html @@ -10,8 +10,8 @@ - - + +

    Scheduling Tasks with Cron Jobs in LAMP

    @@ -34,6 +34,6 @@

  • To install additional modules not included with the standard python3.8 image (for example), you may wish to run pip install commands through a shell script.
  • Use swarm.cronjob.schedule to enter your cron string
  • -

    Do this step for each service you plan to create. After you update the stack, the script should begin running as scheduled. The service above, for instance, will run at daily at 3 AM.

    +

    Do this step for each service you plan to create. After you update the stack, the script should begin running as scheduled. The service above, for instance, will run at daily at 3 AM.

    \ No newline at end of file diff --git a/develop/how_works/index.html b/develop/how_works/index.html index 56ed642805..22b7fbcf90 100644 --- a/develop/how_works/index.html +++ b/develop/how_works/index.html @@ -10,8 +10,8 @@ - - + +

    How the Platform Works

    @@ -71,6 +71,6 @@

    Federated Systems Using the Automation Framework

    Supposing multiple existing systems provided clinically useful sources of data, such as longitudinal imaging repositories or existing Fitbit devices synchronized to the cloud. While data retrieval and ad-hoc storage of “out-of-line” (that is, unrecognized by the Platform, but retaining meaning to its owner) data from within the Platform is simple using the API, it would be simply infeasible to manually verify modified data against multiple specific conditions and run several scripts in the Researcher’s local computer before sending out notifications or awaiting further processing from elsewhere. Instead, the Platform supports, through the Automations framework, a method of dynamically running such scripts as “applets” atop extremely powerful unconstrained hardware not managed by the Researcher or their IT department.

    -

    In the example above, a combination of two applets and an external Amazon S3 database (unknown to the LAMP Platform) provide the equivalent three step upload-process-analyze functionality of apps such as AWARE, Fitbit, Beiwe, Google Fit, and more. The lamp.anomaly_detection applet is not considered a part of this group as it was written to use only the standard API provided by the LAMP Platform; it contains no knowledge of the other two applets and the external database. The org.aware.upload applet requests preallocation of storage, perhaps on the order of ~5GB, but entirely variable depending on the Participant’s device or historical data uploads. It then returns a response immediately to the requesting smartphone device or internet service with a URL to which it can upload the data. The second applet, org.aware.processing is instead run by the Cloud server every 5 minutes to check if any processing needs to be done in the database, and if so, executes the processing, but otherwise does nothing. This applet converts the uploaded data to LAMP Resources (ActivityEvents or SensorEvents, specifically) and submits them to the Cloud server in bulk. Just as with any other events received by the Cloud server, it will then execute a set of Automation applets — in this case, lamp.anomaly_detection. In summary, with this multi-applet workflow, data is automatically uploaded and stored in an external database wholly maintained by a third-party, subsequently converted to actionable reactive LAMP Sensor or ActivityEvents, and finally analyzed through the same methods as all other data.

    +

    In the example above, a combination of two applets and an external Amazon S3 database (unknown to the LAMP Platform) provide the equivalent three step upload-process-analyze functionality of apps such as AWARE, Fitbit, Beiwe, Google Fit, and more. The lamp.anomaly_detection applet is not considered a part of this group as it was written to use only the standard API provided by the LAMP Platform; it contains no knowledge of the other two applets and the external database. The org.aware.upload applet requests preallocation of storage, perhaps on the order of ~5GB, but entirely variable depending on the Participant’s device or historical data uploads. It then returns a response immediately to the requesting smartphone device or internet service with a URL to which it can upload the data. The second applet, org.aware.processing is instead run by the Cloud server every 5 minutes to check if any processing needs to be done in the database, and if so, executes the processing, but otherwise does nothing. This applet converts the uploaded data to LAMP Resources (ActivityEvents or SensorEvents, specifically) and submits them to the Cloud server in bulk. Just as with any other events received by the Cloud server, it will then execute a set of Automation applets — in this case, lamp.anomaly_detection. In summary, with this multi-applet workflow, data is automatically uploaded and stored in an external database wholly maintained by a third-party, subsequently converted to actionable reactive LAMP Sensor or ActivityEvents, and finally analyzed through the same methods as all other data.

    \ No newline at end of file diff --git a/develop/intervention_delivery/index.html b/develop/intervention_delivery/index.html index 529762ebe3..3257813321 100644 --- a/develop/intervention_delivery/index.html +++ b/develop/intervention_delivery/index.html @@ -10,8 +10,8 @@ - - + +

    Continuous Monitoring & Intervention Delivery

    @@ -20,6 +20,6 @@

    Please contact us directly for guidance on delivery of just-in-time interventions.

    Taking the example of a Big Data-powered Clinical Decision Support (CDS) system, it may ingest a vast amount of passive as well as active data to apply heuristics and derive extracted meta-information, upon which machine learning analysis may detect a critical anomaly requiring clinical intervention and support. After notifying the clinician, this system may notify the Participant with an intervention Activity. As the Participant interacts with the newly suggested intervention, newly recorded measurements from the aforementioned sensor instruments will be synchronized to the Cloud server, and this same CDS system will be invoked again to verify that how successful the feedback was.

    -

    Supposing a Participant were not able to remain connected to the network frequently, the mindLAMP app may not be able to communicate with the Cloud server responsible for managing the execution of these Automations. Instead, however, a “low-connectivity” mode is entered, and of all the Automations installed by the Researcher, those specifically designated as capable of low-power processing (and written only in JavaScript, accessing no network or disk resources) will be downloaded and version-synchronized whenever possible. It is this lightweight version of the CDS system that will instead be executed, but the same intervention Activity will be presented to the Participant in the same timely manner. This version of the CDS system might instead rely only on simple heuristic such as the value of a single question related to suicidal ideation, as the processing scale of the Big data-powered variant CDS system would be dramatically greater and unsupportable on smartphone devices.

    +

    Supposing a Participant were not able to remain connected to the network frequently, the mindLAMP app may not be able to communicate with the Cloud server responsible for managing the execution of these Automations. Instead, however, a “low-connectivity” mode is entered, and of all the Automations installed by the Researcher, those specifically designated as capable of low-power processing (and written only in JavaScript, accessing no network or disk resources) will be downloaded and version-synchronized whenever possible. It is this lightweight version of the CDS system that will instead be executed, but the same intervention Activity will be presented to the Participant in the same timely manner. This version of the CDS system might instead rely only on simple heuristic such as the value of a single question related to suicidal ideation, as the processing scale of the Big data-powered variant CDS system would be dramatically greater and unsupportable on smartphone devices.

    \ No newline at end of file diff --git a/develop/intro/index.html b/develop/intro/index.html index b4c437f6e1..766142a916 100644 --- a/develop/intro/index.html +++ b/develop/intro/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/develop/low_power/index.html b/develop/low_power/index.html index 2af648ce79..1b69d68045 100644 --- a/develop/low_power/index.html +++ b/develop/low_power/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/develop/oauth_oidc/index.html b/develop/oauth_oidc/index.html index 022406a830..b9811c7e97 100644 --- a/develop/oauth_oidc/index.html +++ b/develop/oauth_oidc/index.html @@ -10,8 +10,8 @@ - - + +

    OAuth2/OIDC Support

    @@ -128,6 +128,6 @@

    S

    Remember that OAUTH_REDIRECT_URI must be exactly the same as the redirect URI the client was set up with.

    For further specifications on configuring Oauth for Google see the documentation here: https://docs.lamp.digital/deploy/configure_oauth_google

    Kubernetes Example

    -
    mindlamp-server.yml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: mindlamp-server
    labels:
    app: mindlamp-server
    spec:
    replicas: 1
    selector:
    matchLabels:
    app: mindlamp-server
    strategy:
    rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0
    type: RollingUpdate
    template:
    metadata:
    labels:
    app: mindlamp-server
    spec:
    containers:
    - name: server
    image: {redactedValue}/mindlamp_server:latest
    imagePullPolicy: Always
    resources:
    limits:
    cpu: "1000m"
    memory: "2000Mi"
    requests:
    cpu: "50m"
    memory: "100Mi"
    livenessProbe:
    exec:
    command:
    - /bin/sh
    - -c
    - "wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1"
    env:
    - name: CDB
    value: "http://admin:varDbPass@couchdb-internal:5984/"
    - name: NATS_SERVER
    value: message-queue:4222
    - name: REDIS_HOST
    value: redis://cache:6379/0
    - name: HTTPS
    value: "off"
    - name: PUSH_API_GATEWAY
    value: "https://app-gateway.lamp.digital/push"
    - name: PUSH_API_KEY
    value: "varPushAPIKey"
    - name: ROOT_KEY
    value: "varRootKey"
    - name: OAUTH_AUTH_URL
    value: "https://login.microsoftonline.com/*7BredactedValue*7D/oauth2/v2.0/authorize"
    - name: OAUTH_TOKEN_URL
    value: "https://login.microsoftonline.com/common/v2.0/oauth2/token"
    - name: OAUTH_LOGOUT_URL
    value: "https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=api:**B7BredactedValue*7D"
    - name: OAUTH_CLIENT_ID
    value: "varOauthClientId"
    - name: OAUTH_CLIENT_SECRET
    value: "varOauthClientSecret"
    - name: TOKEN_SECRET
    value: "varOauthTokenSecret"
    - name: OAUTH_REDIRECT_URI
    value: "{redactedValue}"
    - name: OAUTH_SCOPE
    value: "openid offline_access"
    - name: OAUTH
    value: "on"
    restartPolicy: Always
    serviceAccountName: ""
    volumes: null
    +
    mindlamp-server.yml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: mindlamp-server
    labels:
    app: mindlamp-server
    spec:
    replicas: 1
    selector:
    matchLabels:
    app: mindlamp-server
    strategy:
    rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0
    type: RollingUpdate
    template:
    metadata:
    labels:
    app: mindlamp-server
    spec:
    containers:
    - name: server
    image: {redactedValue}/mindlamp_server:latest
    imagePullPolicy: Always
    resources:
    limits:
    cpu: "1000m"
    memory: "2000Mi"
    requests:
    cpu: "50m"
    memory: "100Mi"
    livenessProbe:
    exec:
    command:
    - /bin/sh
    - -c
    - "wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1"
    env:
    - name: CDB
    value: "http://admin:varDbPass@couchdb-internal:5984/"
    - name: NATS_SERVER
    value: message-queue:4222
    - name: REDIS_HOST
    value: redis://cache:6379/0
    - name: HTTPS
    value: "off"
    - name: PUSH_API_GATEWAY
    value: "https://app-gateway.lamp.digital/push"
    - name: PUSH_API_KEY
    value: "varPushAPIKey"
    - name: ROOT_KEY
    value: "varRootKey"
    - name: OAUTH_AUTH_URL
    value: "https://login.microsoftonline.com/*7BredactedValue*7D/oauth2/v2.0/authorize"
    - name: OAUTH_TOKEN_URL
    value: "https://login.microsoftonline.com/common/v2.0/oauth2/token"
    - name: OAUTH_LOGOUT_URL
    value: "https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=api:**B7BredactedValue*7D"
    - name: OAUTH_CLIENT_ID
    value: "varOauthClientId"
    - name: OAUTH_CLIENT_SECRET
    value: "varOauthClientSecret"
    - name: TOKEN_SECRET
    value: "varOauthTokenSecret"
    - name: OAUTH_REDIRECT_URI
    value: "{redactedValue}"
    - name: OAUTH_SCOPE
    value: "openid offline_access"
    - name: OAUTH
    value: "on"
    restartPolicy: Always
    serviceAccountName: ""
    volumes: null
    \ No newline at end of file diff --git a/faq/index.html b/faq/index.html index 40e2d8ccc8..ed3696d8f5 100644 --- a/faq/index.html +++ b/faq/index.html @@ -10,8 +10,8 @@ - - + +
    +

    If you require immediate advice on how to solve some commonly encountered issues, please see the Troubleshooting Page

    \ No newline at end of file diff --git a/index.html b/index.html index c25b19035e..4c07ee37b3 100644 --- a/index.html +++ b/index.html @@ -10,8 +10,8 @@ - - + +

    LAMP Platform

    @@ -25,6 +25,6 @@

    ③ DatabaseThe Database securely and chronologically indexes the data through the LAMP Protocol for programming and data science. It informs custom data analysis code in real-time that new patient data has arrived. Researchers can better build reusable tools, analysis pipelines, and conduct reproducible science, knowing that others around the globe using the LAMP Platform can easily work with their data or replicate their unique study.

    ④ Cortex

    The Cortex data analysis pipeline is designed to easily hook into the Database and extract important and clinically useful secondary data features, such as sedentary behavior, time spent at home, device/screen usage, sleep estimates, and much more, from the terabytes of raw data. It can trigger custom just-in-time adaptive interventions and produce useful interactive visualizations viewable by patients and clinicians.

    -

    +
    \ No newline at end of file diff --git a/privacy/index.html b/privacy/index.html index 1bfbc1b7eb..9f4ce7e049 100644 --- a/privacy/index.html +++ b/privacy/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/search-index.json b/search-index.json index 899a3c052f..95ae44bb6a 100644 --- a/search-index.json +++ b/search-index.json @@ -1 +1 @@ -[{"documents":[{"i":1,"t":"Stability & Infrastructure Upgrades","u":"/blog/2020/08/25/","b":["What's New"]},{"i":8,"t":"General Availability of mindLAMP 2","u":"/blog/2020/10/05/","b":["What's New"]},{"i":26,"t":"User Experience Upgrades","u":"/blog/2020/10/15/","b":["What's New"]},{"i":38,"t":"Stability & Performance Improvements","u":"/blog/2020/11/05/","b":["What's New"]},{"i":47,"t":"Clinical Customization Updates","u":"/blog/2020/10/23/","b":["What's New"]},{"i":54,"t":"Ease of Use Improvements","u":"/blog/2020/11/06/","b":["What's New"]},{"i":58,"t":"Stability & Performance Improvements","u":"/blog/2021/01/11/","b":["What's New"]},{"i":66,"t":"Cortex Visualizations & Activity Updates","u":"/blog/2020/12/01/","b":["What's New"]},{"i":78,"t":"Significant Performance Improvements & UI Overhaul","u":"/blog/2021/04/22/","b":["What's New"]},{"i":99,"t":"Documentation Overhaul","u":"/blog/2021/04/01/","b":["What's New"]},{"i":101,"t":"Minor Stability Updates and Bug Fixes","u":"/blog/2021/08/09/","b":["What's New"]},{"i":107,"t":"Visualization & Activity Updates","u":"/blog/2021/08/25/","b":["What's New"]},{"i":113,"t":"Scheduled Routine mindLAMP AWS Maintenance","u":"/blog/2021/09/13/","b":["What's New"]},{"i":115,"t":"New, fully functional Clinical-specific use for mindLAMP!","u":"/blog/2021/11/22/","b":["What's New"]},{"i":123,"t":"New features, stability fixes, and improvements","u":"/blog/2021/12/16/","b":["What's New"]},{"i":131,"t":"","u":"/blog/2022/03/07/","b":["What's New"]},{"i":135,"t":"","u":"/blog/2022/03/22/","b":["What's New"]},{"i":141,"t":"2022 User Interface Improvements","u":"/blog/2022/1/11/","b":["What's New"]},{"i":149,"t":"Ease of Use Improvements","u":"/blog/2020/12/17/","b":["What's New"]},{"i":163,"t":"Patient Profile & New Cognitive Tests","u":"/blog/2021/02/12/","b":["What's New"]},{"i":179,"t":"Release 2022.4.23","u":"/blog/2022/04/23/","b":["What's New"]},{"i":185,"t":"","u":"/blog/2022/2/15/","b":["What's New"]},{"i":191,"t":"","u":"/blog/archive","b":["What's New"]},{"i":192,"t":"","u":"/blog/page/10","b":["What's New"]},{"i":199,"t":"","u":"/blog/page/11","b":["What's New"]},{"i":221,"t":"","u":"/blog/page/12","b":["What's New"]},{"i":224,"t":"","u":"/blog/page/14","b":["What's New"]},{"i":233,"t":"","u":"/blog/page/13","b":["What's New"]},{"i":250,"t":"","u":"/blog/page/16","b":["What's New"]},{"i":263,"t":"","u":"/blog/page/15","b":["What's New"]},{"i":278,"t":"","u":"/blog/page/17","b":["What's New"]},{"i":283,"t":"","u":"/blog/page/2","b":["What's New"]},{"i":289,"t":"","u":"/blog/page/21","b":["What's New"]},{"i":308,"t":"","u":"/blog/page/18","b":["What's New"]},{"i":318,"t":"","u":"/blog/page/19","b":["What's New"]},{"i":326,"t":"","u":"/blog/page/20","b":["What's New"]},{"i":339,"t":"","u":"/blog/page/3","b":["What's New"]},{"i":343,"t":"","u":"/blog/page/22","b":["What's New"]},{"i":351,"t":"","u":"/blog/page/4","b":["What's New"]},{"i":357,"t":"Frontend","u":"/blog/page/5","b":["What's New"]},{"i":365,"t":"New Features","u":"/blog/page/6","b":["What's New"]},{"i":373,"t":"New Features","u":"/blog/page/7","b":["What's New"]},{"i":381,"t":"","u":"/blog/page/8","b":["What's New"]},{"i":384,"t":"","u":"/blog/page/9","b":["What's New"]},{"i":391,"t":"How does LAMP Platform Work?","u":"/about/intro","b":[]},{"i":393,"t":"Publications with LAMP","u":"/about/publications","b":[]},{"i":395,"t":"Who's using LAMP?","u":"/about/users","b":[]},{"i":397,"t":"Report issues","u":"/bug","b":[]},{"i":399,"t":"Admin Checklist","u":"/consortium/admin/checklist","b":[]},{"i":401,"t":"Create an Assess Activity","u":"/consortium/admin/create_assess_activity","b":[]},{"i":403,"t":"Create a DBT Diary Card","u":"/consortium/admin/create_dbt_diary","b":[]},{"i":405,"t":"Create a New Researcher or Clinician Credential","u":"/consortium/admin/create_clinician","b":[]},{"i":407,"t":"Create and Customize Surveys","u":"/consortium/admin/create_survey","b":[]},{"i":409,"t":"Create a Study","u":"/consortium/admin/create_study","b":[]},{"i":411,"t":"Create a Manage Activity","u":"/consortium/admin/create_manage_activity","b":[]},{"i":413,"t":"Create a Tip in Learn","u":"/consortium/admin/create_tip","b":[]},{"i":415,"t":"Create and Rename User","u":"/consortium/admin/create_user","b":[]},{"i":417,"t":"Download mindLAMP","u":"/app","b":[]},{"i":419,"t":"Delete a User or Share Login Link","u":"/consortium/admin/delete_user","b":[]},{"i":421,"t":"Download mindLAMP","u":"/consortium/admin/download","b":[]},{"i":423,"t":"Logging into LAMP","u":"/consortium/admin/login","b":[]},{"i":425,"t":"Reset a Patient's Credentials","u":"/consortium/admin/reset_user","b":[]},{"i":427,"t":"Reset a Clinican or Researcher Password","u":"/consortium/admin/reset_clinician","b":[]},{"i":429,"t":"Schedule or Delete an Activity","u":"/consortium/admin/sched_delete-activity","b":[]},{"i":431,"t":"Guidelines and Principles","u":"/consortium/joining/guidelines","b":[]},{"i":433,"t":"Register your Interest","u":"/consortium/joining/register","b":[]},{"i":435,"t":"Requirements","u":"/consortium/joining/requirements","b":[]},{"i":437,"t":"Introduction","u":"/consortium/joining/intro","b":[]},{"i":439,"t":"Webinars","u":"/consortium/joining/webinars","b":[]},{"i":441,"t":"Download mindLAMP","u":"/consortium/LAC/Clients/download","b":[]},{"i":443,"t":"Add Emotions to the DBT Diary Card","u":"/consortium/LAC/Clients/emotions","b":[]},{"i":445,"t":"Open the DBT Diary Card","u":"/consortium/LAC/Clients/find_dbt","b":[]},{"i":447,"t":"Logging into LAMP","u":"/consortium/LAC/Clients/login","b":[]},{"i":449,"t":"Add Skills to the DBT Diary Card","u":"/consortium/LAC/Clients/skills","b":[]},{"i":451,"t":"Add Target Behaviors to the DBT Diary Card","u":"/consortium/LAC/Clients/targets","b":[]},{"i":453,"t":"Add Additional Notes to the DBT Diary Card","u":"/consortium/LAC/Clients/add_note","b":[]},{"i":455,"t":"Create a DBT Diary Card","u":"/consortium/LAC/Clinicians/create_dbt","b":[]},{"i":457,"t":"Customize a DBT Diary Card","u":"/consortium/LAC/Clinicians/customize","b":[]},{"i":459,"t":"Customize Target Behaviors on a DBT Diary Card","u":"/consortium/LAC/Clinicians/behaviors","b":[]},{"i":461,"t":"Delete a User or Share Login Link","u":"/consortium/LAC/Clinicians/delete_user","b":[]},{"i":463,"t":"Complete a DBT Diary Card for a Client","u":"/consortium/LAC/Clinicians/impersonate","b":[]},{"i":465,"t":"Logging into LAMP","u":"/consortium/LAC/Clinicians/login","b":[]},{"i":467,"t":"Create and Rename a Client","u":"/consortium/LAC/Clinicians/new_user","b":[]},{"i":469,"t":"Reset a Client's Credentials","u":"/consortium/LAC/Clinicians/reset_user","b":[]},{"i":471,"t":"MAPNET","u":"/consortium/mapnet","b":[]},{"i":473,"t":"Create Login Credentials for Clients","u":"/consortium/LAC/Clinicians/user_cred","b":[]},{"i":475,"t":"Customize Emotions on a DBT Diary Card","u":"/consortium/LAC/Clinicians/emotions","b":[]},{"i":477,"t":"Download mindLAMP","u":"/consortium/patient/download","b":[]},{"i":479,"t":"Patient Checklist","u":"/consortium/patient/checklist","b":[]},{"i":481,"t":"Take Surveys and Complete Activities","u":"/consortium/patient/complete_activities","b":[]},{"i":483,"t":"Logging into LAMP","u":"/consortium/patient/login","b":[]},{"i":485,"t":"Read a Tip","u":"/consortium/patient/read_tip","b":[]},{"i":487,"t":"Create a DBT Diary Card for a User.","u":"/consortium/researcher/create_dbt","b":[]},{"i":489,"t":"Create an Assess Activity","u":"/consortium/researcher/create_assess_activity","b":[]},{"i":491,"t":"Researcher Checklist","u":"/consortium/researcher/checklist","b":[]},{"i":493,"t":"Create a Study","u":"/consortium/researcher/create_study","b":[]},{"i":495,"t":"Create a Tip in Learn","u":"/consortium/researcher/create_tip","b":[]},{"i":497,"t":"Create and Customize Surveys","u":"/consortium/researcher/create_survey","b":[]},{"i":499,"t":"Create and Rename User","u":"/consortium/researcher/create_user","b":[]},{"i":501,"t":"Create a DBT Diary Card","u":"/consortium/researcher/DBT/create_dbt_diary","b":[]},{"i":503,"t":"Delete a User or Share Login Link","u":"/consortium/researcher/delete_user","b":[]},{"i":505,"t":"Download mindLAMP","u":"/consortium/researcher/download","b":[]},{"i":507,"t":"Logging into LAMP","u":"/consortium/researcher/login","b":[]},{"i":509,"t":"Create a Manage Activity","u":"/consortium/researcher/create_manage_activity","b":[]},{"i":511,"t":"Schedule or Delete an Activity","u":"/consortium/researcher/sched_delete-activity","b":[]},{"i":513,"t":"Reset a Patient's Credentials","u":"/consortium/researcher/reset_user","b":[]},{"i":515,"t":"Adding Cortex Features","u":"/data_science/cortex/developing_cortex","b":[]},{"i":517,"t":"Accelerometer Jerk","u":"/data_science/cortex/features/primary/acc_jerk","b":[]},{"i":519,"t":"Sleep Periods","u":"/data_science/cortex/features/primary/deprecated_features/sleep_periods","b":[]},{"i":521,"t":"Game level scores","u":"/data_science/cortex/features/primary/game_level_scores","b":[]},{"i":523,"t":"Advanced Usage","u":"/data_science/cortex/advanced","b":[]},{"i":525,"t":"Significant Locations","u":"/data_science/cortex/features/primary/sig_locs","b":[]},{"i":527,"t":"Trips","u":"/data_science/cortex/features/primary/trips","b":[]},{"i":529,"t":"Survey scores","u":"/data_science/cortex/features/primary/survey_scores","b":[]},{"i":531,"t":"Call Degree","u":"/data_science/cortex/features/secondary/call_degree","b":[]},{"i":533,"t":"Call Duration","u":"/data_science/cortex/features/secondary/call_duration","b":[]},{"i":535,"t":"Call Number","u":"/data_science/cortex/features/secondary/call_number","b":[]},{"i":537,"t":"Data Quality","u":"/data_science/cortex/features/secondary/data_quality","b":[]},{"i":539,"t":"Sleep Duration","u":"/data_science/cortex/features/secondary/deprecated_features/sleep_duration","b":[]},{"i":541,"t":"Bluetooth Device Count","u":"/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count","b":[]},{"i":543,"t":"Screen Active","u":"/data_science/cortex/features/primary/screen_active","b":[]},{"i":545,"t":"SMS Number","u":"/data_science/cortex/features/secondary/deprecated_features/sms_number","b":[]},{"i":547,"t":"Entropy","u":"/data_science/cortex/features/secondary/entropy","b":[]},{"i":549,"t":"Primary Feature Overview","u":"/data_science/cortex/features/primary/overview","b":[]},{"i":551,"t":"Healthkit Sleep Duration","u":"/data_science/cortex/features/secondary/healthkit_sleep_duration","b":[]},{"i":553,"t":"Hometime","u":"/data_science/cortex/features/secondary/hometime","b":[]},{"i":555,"t":"Game Results","u":"/data_science/cortex/features/secondary/game_results","b":[]},{"i":557,"t":"Secondary Feature Overview","u":"/data_science/cortex/features/secondary/overview","b":[]},{"i":559,"t":"Inactive Duration","u":"/data_science/cortex/features/secondary/inactive_duration","b":[]},{"i":561,"t":"Screen Duration","u":"/data_science/cortex/features/secondary/screen_duration","b":[]},{"i":563,"t":"Nearby Device Count","u":"/data_science/cortex/features/secondary/nearby_device_count","b":[]},{"i":565,"t":"Step Count","u":"/data_science/cortex/features/secondary/step_count","b":[]},{"i":567,"t":"Survey Results","u":"/data_science/cortex/features/secondary/survey_results","b":[]},{"i":569,"t":"Trip Distance","u":"/data_science/cortex/features/secondary/trip_distance","b":[]},{"i":571,"t":"Trip Duration","u":"/data_science/cortex/features/secondary/trip_duration","b":[]},{"i":573,"t":"Running Cortex","u":"/data_science/cortex/running_cortex","b":[]},{"i":575,"t":"Cortex Quick Start Guide","u":"/data_science/cortex/getting-started","b":[]},{"i":577,"t":"General functions","u":"/data_science/cortex/utils/general_functions","b":[]},{"i":579,"t":"Activity functions","u":"/data_science/cortex/utils/activities","b":[]},{"i":581,"t":"Database functions","u":"/data_science/cortex/utils/database","b":[]},{"i":583,"t":"Sensor functions","u":"/data_science/cortex/utils/sensors","b":[]},{"i":585,"t":"Notifications","u":"/data_science/cortex/utils/notifications","b":[]},{"i":587,"t":"Module scheduler","u":"/data_science/cortex/utils/module_scheduler","b":[]},{"i":589,"t":"Data Quality","u":"/data_science/cortex/visualizations/data_quality","b":[]},{"i":591,"t":"Miscellaneous","u":"/data_science/cortex/utils/miscellaneous","b":[]},{"i":593,"t":"Basic Analysis","u":"/data_science/cortex/visualizations/basic_analysis","b":[]},{"i":595,"t":"Participant-Level Visualizations","u":"/data_science/cortex/visualizations/participant_level","b":[]},{"i":597,"t":"Using the LAMP Data Portal","u":"/data_science/data_portal","b":[]},{"i":599,"t":"How does the LAMP Data Format Work?","u":"/data_science/data","b":[]},{"i":601,"t":"Introduction","u":"/data_science/intro","b":[]},{"i":603,"t":"What is Cortex?","u":"/data_science/cortex/what_is_cortex","b":[]},{"i":605,"t":"Sensor Types","u":"/data_science/data_types/sensor_types","b":[]},{"i":607,"t":"Preparing to Analyze Your Data in Python","u":"/data_science/python","b":[]},{"i":609,"t":"Activity Types","u":"/data_science/data_types/activity_types","b":[]},{"i":611,"t":"Preparing Resources on AWS","u":"/deploy/aws","b":[]},{"i":613,"t":"Deploying via CloudFormation","u":"/deploy/cloudformation","b":[]},{"i":615,"t":"Preparing to Analyze Your Data in R","u":"/data_science/r","b":[]},{"i":617,"t":"Configure OAuth for Google","u":"/deploy/configure_oauth_google","b":[]},{"i":619,"t":"Tags & Attachments","u":"/data_science/tags","b":[]},{"i":621,"t":"Costs of Deploying the LAMP Platform","u":"/deploy/costs","b":[]},{"i":623,"t":"Complex Password Requirements","u":"/deploy/passwords","b":[]},{"i":625,"t":"Prerequisites for Deploying the LAMP Platform","u":"/deploy/prereqs","b":[]},{"i":627,"t":"Provisioning the LAMP Platform","u":"/deploy/provisioning","b":[]},{"i":629,"t":"Deployment Recommendations","u":"/deploy/recs","b":[]},{"i":631,"t":"Configuring your server to add Sensors and Activities","u":"/deploy/enabling_sensors_and_activities","b":[]},{"i":633,"t":"Testing the LAMP Platform","u":"/deploy/testing","b":[]},{"i":635,"t":"Deploying the LAMP Platform","u":"/deploy/deploying","b":[]},{"i":637,"t":"Just-In-Time Adaptive Interventions","u":"/develop/adaptive_interventions","b":[]},{"i":639,"t":"Troubleshooting Deployment","u":"/deploy/troubleshooting","b":[]},{"i":641,"t":"Building New Activities","u":"/develop/build_new_activities","b":[]},{"i":643,"t":"App Gateway","u":"/develop/app_gateway","b":[]},{"i":645,"t":"How the Platform Works","u":"/develop/how_works","b":[]},{"i":647,"t":"Scheduling Tasks with Cron Jobs in LAMP","u":"/develop/cron_jobs","b":[]},{"i":649,"t":"Continuous Monitoring & Intervention Delivery","u":"/develop/intervention_delivery","b":[]},{"i":651,"t":"Components of the LAMP Platform","u":"/develop/intro","b":[]},{"i":653,"t":"Low Power & Connectivity Support","u":"/develop/low_power","b":[]},{"i":655,"t":"Creating a Github Release","u":"/develop/Repositories/creating-github-release","b":[]},{"i":657,"t":"Writing Documentation","u":"/develop/Repositories/writing-documentation","b":[]},{"i":659,"t":"Frequently Asked Questions","u":"/faq","b":[]},{"i":661,"t":"Accessing Your Account","u":"/start_here/accessing_account","b":[]},{"i":663,"t":"Migrating from CouchDB to MongoDB","u":"/develop/couchdb-migration","b":[]},{"i":665,"t":"OAuth2/OIDC Support","u":"/develop/oauth_oidc","b":[]},{"i":667,"t":"Security & Privacy Policy","u":"/privacy","b":[]},{"i":669,"t":"Take Surveys and Complete Activities","u":"/start_here/activities/complete_activities","b":[]},{"i":671,"t":"Activities Currently Available on LAMP","u":"/start_here/activities/activities","b":[]},{"i":673,"t":"Create and Customize Activities","u":"/start_here/activities/create_activities","b":[]},{"i":675,"t":"Affirmations","u":"/start_here/activities/assets/VinfenTips","b":[]},{"i":677,"t":"Customize and Schedule Activities","u":"/start_here/activities/customize_activities","b":[]},{"i":679,"t":"Create and Customize Surveys","u":"/start_here/activities/create_surveys","b":[]},{"i":681,"t":"Checking LAMP battery and data usage","u":"/start_here/battery_data_usage","b":[]},{"i":683,"t":"Training Modules","u":"/develop/Training Modules/training-modules","b":[]},{"i":685,"t":"Delete and Schedule Activities","u":"/start_here/activities/delete_activities","b":[]},{"i":687,"t":"Create and Customize Tips","u":"/start_here/activities/create_tips","b":[]},{"i":689,"t":"Importing, Exporting, and Duplicating Activities","u":"/start_here/import_activities","b":[]},{"i":691,"t":"Care Team - Connection with Patients","u":"/start_here/care_team","b":[]},{"i":693,"t":"Create or Manage Patients and Participants","u":"/start_here/create_patients_participants","b":[]},{"i":695,"t":"Survey Instrument Library","u":"/start_here/instruments","b":[]},{"i":697,"t":"Visualize data","u":"/start_here/activities/visualize","b":[]},{"i":699,"t":"LAMP Updates Tutorial","u":"/start_here/updates_tutorial","b":[]},{"i":701,"t":"How does the mindLAMP app work?","u":"/start_here/overview","b":[]},{"i":703,"t":"Modifying the frequency of a sensor's data collection","u":"/start_here/updating_frequency","b":[]},{"i":705,"t":"Log In Information, Tips, and Tricks","u":"/start_here/logging_in","b":[]},{"i":707,"t":"Wearables","u":"/start_here/wearables","b":[]},{"i":709,"t":"View the Dashboard","u":"/start_here/view_dashboard","b":[]},{"i":711,"t":"Users vs Activities vs Sensors vs Studies Tab","u":"/start_here/users_vs_activities","b":[]},{"i":713,"t":"Adding a Sensor","u":"/start_here/sensors","b":[]},{"i":715,"t":"Troubleshooting","u":"/troubleshooting","b":[]},{"i":717,"t":"A - Assess","u":"/using/assess","b":[]},{"i":719,"t":"M - Manage","u":"/using/manage","b":[]},{"i":721,"t":"Clinical vs. Research Use","u":"/using/clin_vs_res","b":[]},{"i":723,"t":"L - Learn","u":"/using/learn","b":[]},{"i":725,"t":"Notes on Android","u":"/using/notes_on_android_devices","b":[]},{"i":727,"t":"P - Prevent","u":"/using/prevent","b":[]},{"i":729,"t":"Cognitive Games and Assessments","u":"/using/cog_games","b":[]},{"i":731,"t":"Sensor Types","u":"/using/sensors","b":[]},{"i":733,"t":"Surveys","u":"/using/surveys","b":[]},{"i":735,"t":"Creating Activity Groups","u":"/using/clustering_activities","b":[]},{"i":737,"t":"Using Document Transformations","u":"/data_science/jsonata","b":[]}],"index":{"version":"2.3.9","fields":["t"],"fieldVectors":[["t/1",[0,3.044,1,2.435,2,4.118,3,3.696]],["t/8",[4,3.696,5,3.696,6,2.593,7,4.118]],["t/26",[3,4.238,8,2.973,9,4.722]],["t/38",[0,3.044,1,2.435,10,3.418,11,2.788]],["t/47",[12,3.919,13,2.878,14,3.491]],["t/54",[11,3.197,15,4.238,16,3.197]],["t/58",[0,3.044,1,2.435,10,3.418,11,2.788]],["t/66",[1,2.159,14,2.699,17,2.699,18,2.846,19,1.667]],["t/78",[1,1.939,10,2.721,11,2.22,20,2.943,21,3.279,22,2.943]],["t/99",[22,4.967,23,4.593]],["t/101",[0,2.699,14,2.699,24,3.651,25,3.651,26,3.277]],["t/107",[1,2.435,14,3.044,18,3.21,19,1.88]],["t/113",[6,2.299,27,2.472,28,3.651,29,3.277,30,3.651]],["t/115",[6,1.874,12,2.47,16,2.015,31,2.015,32,2.976,33,2.2,34,2.976]],["t/123",[0,2.699,11,2.472,26,3.277,31,2.472,35,2.577]],["t/131",[]],["t/135",[]],["t/141",[8,2.593,11,2.788,36,4.118,37,4.118]],["t/149",[11,3.197,15,4.238,16,3.197]],["t/163",[1,1.939,31,2.22,38,2.556,39,3.279,40,2.943,41,2.943]],["t/179",[42,4.967,43,5.534]],["t/185",[]],["t/191",[]],["t/192",[]],["t/199",[]],["t/221",[]],["t/224",[]],["t/233",[]],["t/250",[]],["t/263",[]],["t/278",[]],["t/283",[]],["t/289",[]],["t/308",[]],["t/318",[]],["t/326",[]],["t/339",[]],["t/343",[]],["t/351",[]],["t/357",[44,6.683]],["t/365",[31,3.747,35,3.906]],["t/373",[31,3.747,35,3.906]],["t/381",[]],["t/384",[]],["t/391",[45,2.244,46,3.078,47,3.681]],["t/393",[45,2.63,48,5.534]],["t/395",[16,3.197,45,2.244,49,4.722]],["t/397",[50,5.534,51,5.534]],["t/399",[52,5.534,53,4.593]],["t/401",[19,2.156,54,2.038,55,3.681]],["t/403",[54,1.777,56,2.302,57,2.302,58,2.302]],["t/405",[31,2.472,54,1.575,59,2.846,60,3.651,61,2.699]],["t/407",[13,2.878,54,2.038,62,2.973]],["t/409",[54,2.388,63,4.593]],["t/411",[19,2.156,54,2.038,64,3.681]],["t/413",[54,2.038,65,3.491,66,3.919]],["t/415",[8,2.973,54,2.038,67,3.919]],["t/417",[6,3.484,68,4.091]],["t/419",[8,2.299,69,2.577,70,3.03,71,2.846,72,3.03]],["t/421",[6,3.484,68,4.091]],["t/423",[45,2.63,73,3.906]],["t/425",[61,3.491,74,3.681,75,4.238]],["t/427",[59,3.21,74,3.21,76,4.118,77,3.696]],["t/429",[19,2.156,27,3.197,69,3.333]],["t/431",[78,5.534,79,5.534]],["t/433",[80,5.534,81,5.534]],["t/435",[82,5.998]],["t/437",[83,5.998]],["t/439",[84,6.683]],["t/441",[6,3.484,68,4.091]],["t/443",[56,2.041,57,2.041,58,2.041,85,2.699,86,3.277]],["t/445",[56,2.302,57,2.302,58,2.302,87,4.118]],["t/447",[45,2.63,73,3.906]],["t/449",[56,2.041,57,2.041,58,2.041,85,2.699,88,3.651]],["t/451",[56,1.833,57,1.833,58,1.833,85,2.424,89,2.943,90,2.943]],["t/453",[56,1.833,57,1.833,58,1.833,85,2.424,91,3.279,92,2.943]],["t/455",[54,1.777,56,2.302,57,2.302,58,2.302]],["t/457",[13,2.51,56,2.302,57,2.302,58,2.302]],["t/459",[13,1.999,56,1.833,57,1.833,58,1.833,89,2.943,90,2.943]],["t/461",[8,2.299,69,2.577,70,3.03,71,2.846,72,3.03]],["t/463",[56,2.041,57,2.041,58,2.041,93,3.03,94,3.03]],["t/465",[45,2.63,73,3.906]],["t/467",[54,2.038,67,3.919,94,3.919]],["t/469",[61,3.491,74,3.681,95,4.722]],["t/471",[96,6.683]],["t/473",[54,1.777,61,3.044,71,3.21,94,3.418]],["t/475",[13,2.225,56,2.041,57,2.041,58,2.041,86,3.277]],["t/477",[6,3.484,68,4.091]],["t/479",[38,4.314,53,4.593]],["t/481",[19,1.88,62,2.593,93,3.418,97,3.696]],["t/483",[45,2.63,73,3.906]],["t/485",[65,4.091,98,5.534]],["t/487",[8,2.299,54,1.575,56,2.041,57,2.041,58,2.041]],["t/489",[19,2.156,54,2.038,55,3.681]],["t/491",[53,4.593,59,4.314]],["t/493",[54,2.388,63,4.593]],["t/495",[54,2.038,65,3.491,66,3.919]],["t/497",[13,2.878,54,2.038,62,2.973]],["t/499",[8,2.973,54,2.038,67,3.919]],["t/501",[54,1.777,56,2.302,57,2.302,58,2.302]],["t/503",[8,2.299,69,2.577,70,3.03,71,2.846,72,3.03]],["t/505",[6,3.484,68,4.091]],["t/507",[45,2.63,73,3.906]],["t/509",[19,2.156,54,2.038,64,3.681]],["t/511",[19,2.156,27,3.197,69,3.333]],["t/513",[61,3.491,74,3.681,75,4.238]],["t/515",[17,3.491,35,3.333,99,4.238]],["t/517",[100,5.534,101,5.534]],["t/519",[102,4.593,103,5.534]],["t/521",[104,3.919,105,4.238,106,4.238]],["t/523",[107,5.534,108,4.967]],["t/525",[20,4.967,109,5.534]],["t/527",[110,5.547]],["t/529",[62,3.484,106,4.967]],["t/531",[111,4.593,112,5.534]],["t/533",[111,4.593,113,3.906]],["t/535",[111,4.593,114,4.967]],["t/537",[115,3.484,116,4.967]],["t/539",[102,4.593,113,3.906]],["t/541",[117,4.722,118,4.238,119,3.919]],["t/543",[19,2.527,120,4.967]],["t/545",[114,4.967,121,5.534]],["t/547",[122,6.683]],["t/549",[35,3.333,123,4.722,124,4.238]],["t/551",[102,3.919,113,3.333,125,4.722]],["t/553",[126,6.683]],["t/555",[104,4.593,127,4.967]],["t/557",[35,3.333,124,4.238,128,4.722]],["t/559",[113,3.906,129,5.534]],["t/561",[113,3.906,120,4.967]],["t/563",[118,4.238,119,3.919,130,4.722]],["t/565",[119,4.593,131,5.534]],["t/567",[62,3.484,127,4.967]],["t/569",[110,4.593,132,5.534]],["t/571",[110,4.593,113,3.906]],["t/573",[17,4.091,133,5.534]],["t/575",[17,3.044,134,4.118,135,4.118,136,4.118]],["t/577",[4,4.967,33,4.091]],["t/579",[19,2.527,33,4.091]],["t/581",[33,4.091,137,5.534]],["t/583",[33,4.091,138,3.906]],["t/585",[139,6.683]],["t/587",[27,3.747,140,4.967]],["t/589",[115,3.484,116,4.967]],["t/591",[141,6.683]],["t/593",[142,5.534,143,5.534]],["t/595",[18,3.681,105,4.238,144,4.238]],["t/597",[16,2.788,45,1.957,115,2.593,145,4.118]],["t/599",[45,1.957,47,3.21,115,2.593,146,4.118]],["t/601",[83,5.998]],["t/603",[17,4.941]],["t/605",[138,3.906,147,4.593]],["t/607",[115,2.593,148,3.418,149,3.696,150,4.118]],["t/609",[19,2.527,147,4.593]],["t/611",[29,4.238,148,3.919,151,4.722]],["t/613",[152,3.333,153,4.722,154,4.722]],["t/615",[115,2.593,148,3.418,149,3.696,155,4.118]],["t/617",[156,4.238,157,4.722,158,4.722]],["t/619",[1,2.792,159,4.722,160,4.722]],["t/621",[45,1.957,46,2.685,152,2.906,161,4.118]],["t/623",[77,4.238,82,4.238,162,4.722]],["t/625",[45,1.957,46,2.685,152,2.906,163,4.118]],["t/627",[45,2.244,46,3.078,164,4.722]],["t/629",[152,3.906,165,5.534]],["t/631",[19,1.667,85,2.699,138,2.577,156,3.277,166,3.651]],["t/633",[41,4.238,45,2.244,46,3.078]],["t/635",[45,2.244,46,3.078,152,3.333]],["t/637",[167,4.722,168,4.722,169,4.238]],["t/639",[152,3.906,170,4.967]],["t/641",[19,2.156,31,3.197,171,4.722]],["t/643",[172,4.967,173,5.534]],["t/645",[46,3.608,47,4.314]],["t/647",[27,2.472,45,1.735,174,3.651,175,3.651,176,3.651]],["t/649",[1,2.159,169,3.277,177,3.651,178,3.651,179,3.651]],["t/651",[45,2.244,46,3.078,180,4.722]],["t/653",[1,2.159,181,3.651,182,3.651,183,3.277,184,3.277]],["t/655",[42,4.238,54,2.038,185,4.722]],["t/657",[23,4.593,186,5.534]],["t/659",[187,4.722,188,4.722,189,4.722]],["t/661",[190,5.534,191,5.534]],["t/663",[192,4.722,193,4.722,194,4.722]],["t/665",[184,4.967,195,5.534]],["t/667",[1,2.435,196,4.118,197,4.118,198,4.118]],["t/669",[19,1.88,62,2.593,93,3.418,97,3.696]],["t/671",[5,3.696,19,1.88,45,1.957,199,4.118]],["t/673",[13,2.878,19,2.156,54,2.038]],["t/675",[200,6.683]],["t/677",[13,2.878,19,2.156,27,3.197]],["t/679",[13,2.878,54,2.038,62,2.973]],["t/681",[45,1.735,108,3.277,115,2.299,201,3.651,202,3.651]],["t/683",[140,4.967,203,5.534]],["t/685",[19,2.156,27,3.197,69,3.333]],["t/687",[13,2.878,54,2.038,65,3.491]],["t/689",[19,1.88,204,4.118,205,4.118,206,4.118]],["t/691",[38,3.21,183,3.696,207,4.118,208,4.118]],["t/693",[38,3.21,54,1.777,64,3.21,144,3.696]],["t/695",[62,2.973,209,4.722,210,4.722]],["t/697",[18,4.314,115,3.484]],["t/699",[14,3.491,45,2.244,211,4.722]],["t/701",[6,2.973,47,3.681,172,4.238]],["t/703",[115,2.299,212,3.651,213,3.651,214,3.651,215,3.651]],["t/705",[65,3.044,73,2.906,216,4.118,217,4.118]],["t/707",[218,6.683]],["t/709",[219,5.534,220,5.534]],["t/711",[8,1.715,19,1.244,63,2.261,138,1.922,221,4.9,222,2.724]],["t/713",[99,4.967,138,3.906]],["t/715",[170,5.998]],["t/717",[55,5.21]],["t/719",[64,4.314,223,5.534]],["t/721",[12,3.418,16,2.788,59,3.21,221,3.696]],["t/723",[66,4.593,224,5.534]],["t/725",[92,4.967,225,5.534]],["t/727",[226,5.534,227,5.534]],["t/729",[40,4.238,55,3.681,104,3.919]],["t/731",[138,3.906,147,4.593]],["t/733",[62,4.208]],["t/735",[19,2.156,54,2.038,228,4.722]],["t/737",[16,3.197,23,3.919,229,4.722]]],"invertedIndex":[["",{"_index":1,"t":{"1":{"position":[[10,1]]},"38":{"position":[[10,1]]},"58":{"position":[[10,1]]},"66":{"position":[[22,1]]},"78":{"position":[[37,1]]},"107":{"position":[[14,1]]},"163":{"position":[[16,1]]},"619":{"position":[[5,1]]},"649":{"position":[[22,1]]},"653":{"position":[[10,1]]},"667":{"position":[[9,1]]}}}],["2",{"_index":7,"t":{"8":{"position":[[33,1]]}}}],["2022",{"_index":36,"t":{"141":{"position":[[0,4]]}}}],["2022.4.23",{"_index":43,"t":{"179":{"position":[[8,9]]}}}],["acceleromet",{"_index":100,"t":{"517":{"position":[[0,13]]}}}],["access",{"_index":190,"t":{"661":{"position":[[0,9]]}}}],["account",{"_index":191,"t":{"661":{"position":[[15,7]]}}}],["activ",{"_index":19,"t":{"66":{"position":[[24,8]]},"107":{"position":[[16,8]]},"401":{"position":[[17,8]]},"411":{"position":[[16,8]]},"429":{"position":[[22,8]]},"481":{"position":[[26,10]]},"489":{"position":[[17,8]]},"509":{"position":[[16,8]]},"511":{"position":[[22,8]]},"543":{"position":[[7,6]]},"579":{"position":[[0,8]]},"609":{"position":[[0,8]]},"631":{"position":[[43,10]]},"641":{"position":[[13,10]]},"669":{"position":[[26,10]]},"671":{"position":[[0,10]]},"673":{"position":[[21,10]]},"677":{"position":[[23,10]]},"685":{"position":[[20,10]]},"689":{"position":[[38,10]]},"711":{"position":[[9,10]]},"735":{"position":[[9,8]]}}}],["ad",{"_index":99,"t":{"515":{"position":[[0,6]]},"713":{"position":[[0,6]]}}}],["adapt",{"_index":168,"t":{"637":{"position":[[13,8]]}}}],["add",{"_index":85,"t":{"443":{"position":[[0,3]]},"449":{"position":[[0,3]]},"451":{"position":[[0,3]]},"453":{"position":[[0,3]]},"631":{"position":[[27,3]]}}}],["addit",{"_index":91,"t":{"453":{"position":[[4,10]]}}}],["admin",{"_index":52,"t":{"399":{"position":[[0,5]]}}}],["advanc",{"_index":107,"t":{"523":{"position":[[0,8]]}}}],["affirm",{"_index":200,"t":{"675":{"position":[[0,12]]}}}],["analysi",{"_index":143,"t":{"593":{"position":[[6,8]]}}}],["analyz",{"_index":149,"t":{"607":{"position":[[13,7]]},"615":{"position":[[13,7]]}}}],["android",{"_index":225,"t":{"725":{"position":[[9,7]]}}}],["app",{"_index":172,"t":{"643":{"position":[[0,3]]},"701":{"position":[[22,3]]}}}],["ask",{"_index":188,"t":{"659":{"position":[[11,5]]}}}],["assess",{"_index":55,"t":{"401":{"position":[[10,6]]},"489":{"position":[[10,6]]},"717":{"position":[[4,6]]},"729":{"position":[[20,11]]}}}],["attach",{"_index":160,"t":{"619":{"position":[[7,11]]}}}],["avail",{"_index":5,"t":{"8":{"position":[[8,12]]},"671":{"position":[[21,9]]}}}],["aw",{"_index":29,"t":{"113":{"position":[[27,3]]},"611":{"position":[[23,3]]}}}],["basic",{"_index":142,"t":{"593":{"position":[[0,5]]}}}],["batteri",{"_index":202,"t":{"681":{"position":[[14,7]]}}}],["behavior",{"_index":90,"t":{"451":{"position":[[11,9]]},"459":{"position":[[17,9]]}}}],["bluetooth",{"_index":117,"t":{"541":{"position":[[0,9]]}}}],["bug",{"_index":25,"t":{"101":{"position":[[28,3]]}}}],["build",{"_index":171,"t":{"641":{"position":[[0,8]]}}}],["call",{"_index":111,"t":{"531":{"position":[[0,4]]},"533":{"position":[[0,4]]},"535":{"position":[[0,4]]}}}],["card",{"_index":58,"t":{"403":{"position":[[19,4]]},"443":{"position":[[30,4]]},"445":{"position":[[19,4]]},"449":{"position":[[28,4]]},"451":{"position":[[38,4]]},"453":{"position":[[38,4]]},"455":{"position":[[19,4]]},"457":{"position":[[22,4]]},"459":{"position":[[42,4]]},"463":{"position":[[21,4]]},"475":{"position":[[34,4]]},"487":{"position":[[19,4]]},"501":{"position":[[19,4]]}}}],["care",{"_index":207,"t":{"691":{"position":[[0,4]]}}}],["check",{"_index":201,"t":{"681":{"position":[[0,8]]}}}],["checklist",{"_index":53,"t":{"399":{"position":[[6,9]]},"479":{"position":[[8,9]]},"491":{"position":[[11,9]]}}}],["client",{"_index":94,"t":{"463":{"position":[[32,6]]},"467":{"position":[[20,6]]},"473":{"position":[[29,7]]}}}],["client'",{"_index":95,"t":{"469":{"position":[[8,8]]}}}],["clinic",{"_index":12,"t":{"47":{"position":[[0,8]]},"115":{"position":[[22,8]]},"721":{"position":[[0,8]]}}}],["clinican",{"_index":76,"t":{"427":{"position":[[8,8]]}}}],["clinician",{"_index":60,"t":{"405":{"position":[[27,9]]}}}],["cloudform",{"_index":154,"t":{"613":{"position":[[14,14]]}}}],["cognit",{"_index":40,"t":{"163":{"position":[[22,9]]},"729":{"position":[[0,9]]}}}],["collect",{"_index":215,"t":{"703":{"position":[[43,10]]}}}],["complet",{"_index":93,"t":{"463":{"position":[[0,8]]},"481":{"position":[[17,8]]},"669":{"position":[[17,8]]}}}],["complex",{"_index":162,"t":{"623":{"position":[[0,7]]}}}],["compon",{"_index":180,"t":{"651":{"position":[[0,10]]}}}],["configur",{"_index":156,"t":{"617":{"position":[[0,9]]},"631":{"position":[[0,11]]}}}],["connect",{"_index":183,"t":{"653":{"position":[[12,12]]},"691":{"position":[[12,10]]}}}],["continu",{"_index":177,"t":{"649":{"position":[[0,10]]}}}],["cortex",{"_index":17,"t":{"66":{"position":[[0,6]]},"515":{"position":[[7,6]]},"573":{"position":[[8,6]]},"575":{"position":[[0,6]]},"603":{"position":[[8,7]]}}}],["cost",{"_index":161,"t":{"621":{"position":[[0,5]]}}}],["couchdb",{"_index":193,"t":{"663":{"position":[[15,7]]}}}],["count",{"_index":119,"t":{"541":{"position":[[17,5]]},"563":{"position":[[14,5]]},"565":{"position":[[5,5]]}}}],["creat",{"_index":54,"t":{"401":{"position":[[0,6]]},"403":{"position":[[0,6]]},"405":{"position":[[0,6]]},"407":{"position":[[0,6]]},"409":{"position":[[0,6]]},"411":{"position":[[0,6]]},"413":{"position":[[0,6]]},"415":{"position":[[0,6]]},"455":{"position":[[0,6]]},"467":{"position":[[0,6]]},"473":{"position":[[0,6]]},"487":{"position":[[0,6]]},"489":{"position":[[0,6]]},"493":{"position":[[0,6]]},"495":{"position":[[0,6]]},"497":{"position":[[0,6]]},"499":{"position":[[0,6]]},"501":{"position":[[0,6]]},"509":{"position":[[0,6]]},"655":{"position":[[0,8]]},"673":{"position":[[0,6]]},"679":{"position":[[0,6]]},"687":{"position":[[0,6]]},"693":{"position":[[0,6]]},"735":{"position":[[0,8]]}}}],["credenti",{"_index":61,"t":{"405":{"position":[[37,10]]},"425":{"position":[[18,11]]},"469":{"position":[[17,11]]},"473":{"position":[[13,11]]},"513":{"position":[[18,11]]}}}],["cron",{"_index":175,"t":{"647":{"position":[[22,4]]}}}],["current",{"_index":199,"t":{"671":{"position":[[11,9]]}}}],["custom",{"_index":13,"t":{"47":{"position":[[9,13]]},"407":{"position":[[11,9]]},"457":{"position":[[0,9]]},"459":{"position":[[0,9]]},"475":{"position":[[0,9]]},"497":{"position":[[11,9]]},"673":{"position":[[11,9]]},"677":{"position":[[0,9]]},"679":{"position":[[11,9]]},"687":{"position":[[11,9]]}}}],["dashboard",{"_index":220,"t":{"709":{"position":[[9,9]]}}}],["data",{"_index":115,"t":{"537":{"position":[[0,4]]},"589":{"position":[[0,4]]},"597":{"position":[[15,4]]},"599":{"position":[[18,4]]},"607":{"position":[[26,4]]},"615":{"position":[[26,4]]},"681":{"position":[[26,4]]},"697":{"position":[[10,4]]},"703":{"position":[[38,4]]}}}],["databas",{"_index":137,"t":{"581":{"position":[[0,8]]}}}],["dbt",{"_index":56,"t":{"403":{"position":[[9,3]]},"443":{"position":[[20,3]]},"445":{"position":[[9,3]]},"449":{"position":[[18,3]]},"451":{"position":[[28,3]]},"453":{"position":[[28,3]]},"455":{"position":[[9,3]]},"457":{"position":[[12,3]]},"459":{"position":[[32,3]]},"463":{"position":[[11,3]]},"475":{"position":[[24,3]]},"487":{"position":[[9,3]]},"501":{"position":[[9,3]]}}}],["degre",{"_index":112,"t":{"531":{"position":[[5,6]]}}}],["delet",{"_index":69,"t":{"419":{"position":[[0,6]]},"429":{"position":[[12,6]]},"461":{"position":[[0,6]]},"503":{"position":[[0,6]]},"511":{"position":[[12,6]]},"685":{"position":[[0,6]]}}}],["deliveri",{"_index":179,"t":{"649":{"position":[[37,8]]}}}],["deploy",{"_index":152,"t":{"613":{"position":[[0,9]]},"621":{"position":[[9,9]]},"625":{"position":[[18,9]]},"629":{"position":[[0,10]]},"635":{"position":[[0,9]]},"639":{"position":[[16,10]]}}}],["devic",{"_index":118,"t":{"541":{"position":[[10,6]]},"563":{"position":[[7,6]]}}}],["diari",{"_index":57,"t":{"403":{"position":[[13,5]]},"443":{"position":[[24,5]]},"445":{"position":[[13,5]]},"449":{"position":[[22,5]]},"451":{"position":[[32,5]]},"453":{"position":[[32,5]]},"455":{"position":[[13,5]]},"457":{"position":[[16,5]]},"459":{"position":[[36,5]]},"463":{"position":[[15,5]]},"475":{"position":[[28,5]]},"487":{"position":[[13,5]]},"501":{"position":[[13,5]]}}}],["distanc",{"_index":132,"t":{"569":{"position":[[5,8]]}}}],["document",{"_index":23,"t":{"99":{"position":[[0,13]]},"657":{"position":[[8,13]]},"737":{"position":[[6,8]]}}}],["download",{"_index":68,"t":{"417":{"position":[[0,8]]},"421":{"position":[[0,8]]},"441":{"position":[[0,8]]},"477":{"position":[[0,8]]},"505":{"position":[[0,8]]}}}],["duplic",{"_index":206,"t":{"689":{"position":[[26,11]]}}}],["durat",{"_index":113,"t":{"533":{"position":[[5,8]]},"539":{"position":[[6,8]]},"551":{"position":[[16,8]]},"559":{"position":[[9,8]]},"561":{"position":[[7,8]]},"571":{"position":[[5,8]]}}}],["eas",{"_index":15,"t":{"54":{"position":[[0,4]]},"149":{"position":[[0,4]]}}}],["emot",{"_index":86,"t":{"443":{"position":[[4,8]]},"475":{"position":[[10,8]]}}}],["entropi",{"_index":122,"t":{"547":{"position":[[0,7]]}}}],["experi",{"_index":9,"t":{"26":{"position":[[5,10]]}}}],["export",{"_index":205,"t":{"689":{"position":[[11,10]]}}}],["featur",{"_index":35,"t":{"123":{"position":[[4,9]]},"365":{"position":[[4,8]]},"373":{"position":[[4,8]]},"515":{"position":[[14,8]]},"549":{"position":[[8,7]]},"557":{"position":[[10,7]]}}}],["fix",{"_index":26,"t":{"101":{"position":[[32,5]]},"123":{"position":[[24,6]]}}}],["format",{"_index":146,"t":{"599":{"position":[[23,6]]}}}],["frequenc",{"_index":213,"t":{"703":{"position":[[14,9]]}}}],["frequent",{"_index":187,"t":{"659":{"position":[[0,10]]}}}],["frontend",{"_index":44,"t":{"357":{"position":[[0,8]]}}}],["fulli",{"_index":32,"t":{"115":{"position":[[5,5]]}}}],["function",{"_index":33,"t":{"115":{"position":[[11,10]]},"577":{"position":[[8,9]]},"579":{"position":[[9,9]]},"581":{"position":[[9,9]]},"583":{"position":[[7,9]]}}}],["game",{"_index":104,"t":{"521":{"position":[[0,4]]},"555":{"position":[[0,4]]},"729":{"position":[[10,5]]}}}],["gateway",{"_index":173,"t":{"643":{"position":[[4,7]]}}}],["gener",{"_index":4,"t":{"8":{"position":[[0,7]]},"577":{"position":[[0,7]]}}}],["github",{"_index":185,"t":{"655":{"position":[[11,6]]}}}],["googl",{"_index":158,"t":{"617":{"position":[[20,6]]}}}],["group",{"_index":228,"t":{"735":{"position":[[18,6]]}}}],["guid",{"_index":136,"t":{"575":{"position":[[19,5]]}}}],["guidelin",{"_index":78,"t":{"431":{"position":[[0,10]]}}}],["healthkit",{"_index":125,"t":{"551":{"position":[[0,9]]}}}],["hometim",{"_index":126,"t":{"553":{"position":[[0,8]]}}}],["import",{"_index":204,"t":{"689":{"position":[[0,10]]}}}],["improv",{"_index":11,"t":{"38":{"position":[[24,12]]},"54":{"position":[[12,12]]},"58":{"position":[[24,12]]},"78":{"position":[[24,12]]},"123":{"position":[[35,12]]},"141":{"position":[[20,12]]},"149":{"position":[[12,12]]}}}],["inact",{"_index":129,"t":{"559":{"position":[[0,8]]}}}],["inform",{"_index":216,"t":{"705":{"position":[[7,12]]}}}],["infrastructur",{"_index":2,"t":{"1":{"position":[[12,14]]}}}],["instrument",{"_index":209,"t":{"695":{"position":[[7,10]]}}}],["interest",{"_index":81,"t":{"433":{"position":[[14,8]]}}}],["interfac",{"_index":37,"t":{"141":{"position":[[10,9]]}}}],["intervent",{"_index":169,"t":{"637":{"position":[[22,13]]},"649":{"position":[[24,12]]}}}],["introduct",{"_index":83,"t":{"437":{"position":[[0,12]]},"601":{"position":[[0,12]]}}}],["issu",{"_index":51,"t":{"397":{"position":[[7,6]]}}}],["jerk",{"_index":101,"t":{"517":{"position":[[14,4]]}}}],["job",{"_index":176,"t":{"647":{"position":[[27,4]]}}}],["l",{"_index":224,"t":{"723":{"position":[[0,1]]}}}],["lamp",{"_index":45,"t":{"391":{"position":[[9,4]]},"393":{"position":[[18,4]]},"395":{"position":[[12,5]]},"423":{"position":[[13,4]]},"447":{"position":[[13,4]]},"465":{"position":[[13,4]]},"483":{"position":[[13,4]]},"507":{"position":[[13,4]]},"597":{"position":[[10,4]]},"599":{"position":[[13,4]]},"621":{"position":[[23,4]]},"625":{"position":[[32,4]]},"627":{"position":[[17,4]]},"633":{"position":[[12,4]]},"635":{"position":[[14,4]]},"647":{"position":[[35,4]]},"651":{"position":[[18,4]]},"671":{"position":[[34,4]]},"681":{"position":[[9,4]]},"699":{"position":[[0,4]]}}}],["learn",{"_index":66,"t":{"413":{"position":[[16,5]]},"495":{"position":[[16,5]]},"723":{"position":[[4,5]]}}}],["level",{"_index":105,"t":{"521":{"position":[[5,5]]},"595":{"position":[[12,5]]}}}],["librari",{"_index":210,"t":{"695":{"position":[[18,7]]}}}],["link",{"_index":72,"t":{"419":{"position":[[29,4]]},"461":{"position":[[29,4]]},"503":{"position":[[29,4]]}}}],["locat",{"_index":109,"t":{"525":{"position":[[12,9]]}}}],["log",{"_index":73,"t":{"423":{"position":[[0,7]]},"447":{"position":[[0,7]]},"465":{"position":[[0,7]]},"483":{"position":[[0,7]]},"507":{"position":[[0,7]]},"705":{"position":[[0,3]]}}}],["login",{"_index":71,"t":{"419":{"position":[[23,5]]},"461":{"position":[[23,5]]},"473":{"position":[[7,5]]},"503":{"position":[[23,5]]}}}],["low",{"_index":181,"t":{"653":{"position":[[0,3]]}}}],["m",{"_index":223,"t":{"719":{"position":[[0,1]]}}}],["mainten",{"_index":30,"t":{"113":{"position":[[31,11]]}}}],["manag",{"_index":64,"t":{"411":{"position":[[9,6]]},"509":{"position":[[9,6]]},"693":{"position":[[10,6]]},"719":{"position":[[4,6]]}}}],["mapnet",{"_index":96,"t":{"471":{"position":[[0,6]]}}}],["migrat",{"_index":192,"t":{"663":{"position":[[0,9]]}}}],["mindlamp",{"_index":6,"t":{"8":{"position":[[24,8]]},"113":{"position":[[18,8]]},"115":{"position":[[48,9]]},"417":{"position":[[9,8]]},"421":{"position":[[9,8]]},"441":{"position":[[9,8]]},"477":{"position":[[9,8]]},"505":{"position":[[9,8]]},"701":{"position":[[13,8]]}}}],["minor",{"_index":24,"t":{"101":{"position":[[0,5]]}}}],["miscellan",{"_index":141,"t":{"591":{"position":[[0,13]]}}}],["modifi",{"_index":212,"t":{"703":{"position":[[0,9]]}}}],["modul",{"_index":140,"t":{"587":{"position":[[0,6]]},"683":{"position":[[9,7]]}}}],["mongodb",{"_index":194,"t":{"663":{"position":[[26,7]]}}}],["monitor",{"_index":178,"t":{"649":{"position":[[11,10]]}}}],["nearbi",{"_index":130,"t":{"563":{"position":[[0,6]]}}}],["new",{"_index":31,"t":{"115":{"position":[[0,4]]},"123":{"position":[[0,3]]},"163":{"position":[[18,3]]},"365":{"position":[[0,3]]},"373":{"position":[[0,3]]},"405":{"position":[[9,3]]},"641":{"position":[[9,3]]}}}],["note",{"_index":92,"t":{"453":{"position":[[15,5]]},"725":{"position":[[0,5]]}}}],["notif",{"_index":139,"t":{"585":{"position":[[0,13]]}}}],["number",{"_index":114,"t":{"535":{"position":[[5,6]]},"545":{"position":[[4,6]]}}}],["oauth",{"_index":157,"t":{"617":{"position":[[10,5]]}}}],["oauth2/oidc",{"_index":195,"t":{"665":{"position":[[0,11]]}}}],["open",{"_index":87,"t":{"445":{"position":[[0,4]]}}}],["overhaul",{"_index":22,"t":{"78":{"position":[[42,8]]},"99":{"position":[[14,8]]}}}],["overview",{"_index":124,"t":{"549":{"position":[[16,8]]},"557":{"position":[[18,8]]}}}],["p",{"_index":226,"t":{"727":{"position":[[0,1]]}}}],["particip",{"_index":144,"t":{"595":{"position":[[0,11]]},"693":{"position":[[30,12]]}}}],["password",{"_index":77,"t":{"427":{"position":[[31,8]]},"623":{"position":[[8,8]]}}}],["patient",{"_index":38,"t":{"163":{"position":[[0,7]]},"479":{"position":[[0,7]]},"691":{"position":[[28,8]]},"693":{"position":[[17,8]]}}}],["patient'",{"_index":75,"t":{"425":{"position":[[8,9]]},"513":{"position":[[8,9]]}}}],["perform",{"_index":10,"t":{"38":{"position":[[12,11]]},"58":{"position":[[12,11]]},"78":{"position":[[12,11]]}}}],["period",{"_index":103,"t":{"519":{"position":[[6,7]]}}}],["platform",{"_index":46,"t":{"391":{"position":[[14,8]]},"621":{"position":[[28,8]]},"625":{"position":[[37,8]]},"627":{"position":[[22,8]]},"633":{"position":[[17,8]]},"635":{"position":[[19,8]]},"645":{"position":[[8,8]]},"651":{"position":[[23,8]]}}}],["polici",{"_index":198,"t":{"667":{"position":[[19,6]]}}}],["portal",{"_index":145,"t":{"597":{"position":[[20,6]]}}}],["power",{"_index":182,"t":{"653":{"position":[[4,5]]}}}],["prepar",{"_index":148,"t":{"607":{"position":[[0,9]]},"611":{"position":[[0,9]]},"615":{"position":[[0,9]]}}}],["prerequisit",{"_index":163,"t":{"625":{"position":[[0,13]]}}}],["prevent",{"_index":227,"t":{"727":{"position":[[4,7]]}}}],["primari",{"_index":123,"t":{"549":{"position":[[0,7]]}}}],["principl",{"_index":79,"t":{"431":{"position":[[15,10]]}}}],["privaci",{"_index":197,"t":{"667":{"position":[[11,7]]}}}],["profil",{"_index":39,"t":{"163":{"position":[[8,7]]}}}],["provis",{"_index":164,"t":{"627":{"position":[[0,12]]}}}],["public",{"_index":48,"t":{"393":{"position":[[0,12]]}}}],["python",{"_index":150,"t":{"607":{"position":[[34,6]]}}}],["qualiti",{"_index":116,"t":{"537":{"position":[[5,7]]},"589":{"position":[[5,7]]}}}],["question",{"_index":189,"t":{"659":{"position":[[17,9]]}}}],["quick",{"_index":134,"t":{"575":{"position":[[7,5]]}}}],["r",{"_index":155,"t":{"615":{"position":[[34,1]]}}}],["read",{"_index":98,"t":{"485":{"position":[[0,4]]}}}],["recommend",{"_index":165,"t":{"629":{"position":[[11,15]]}}}],["regist",{"_index":80,"t":{"433":{"position":[[0,8]]}}}],["releas",{"_index":42,"t":{"179":{"position":[[0,7]]},"655":{"position":[[18,7]]}}}],["renam",{"_index":67,"t":{"415":{"position":[[11,6]]},"467":{"position":[[11,6]]},"499":{"position":[[11,6]]}}}],["report",{"_index":50,"t":{"397":{"position":[[0,6]]}}}],["requir",{"_index":82,"t":{"435":{"position":[[0,12]]},"623":{"position":[[17,12]]}}}],["research",{"_index":59,"t":{"405":{"position":[[13,10]]},"427":{"position":[[20,10]]},"491":{"position":[[0,10]]},"721":{"position":[[13,8]]}}}],["reset",{"_index":74,"t":{"425":{"position":[[0,5]]},"427":{"position":[[0,5]]},"469":{"position":[[0,5]]},"513":{"position":[[0,5]]}}}],["resourc",{"_index":151,"t":{"611":{"position":[[10,9]]}}}],["result",{"_index":127,"t":{"555":{"position":[[5,7]]},"567":{"position":[[7,7]]}}}],["routin",{"_index":28,"t":{"113":{"position":[[10,7]]}}}],["run",{"_index":133,"t":{"573":{"position":[[0,7]]}}}],["schedul",{"_index":27,"t":{"113":{"position":[[0,9]]},"429":{"position":[[0,8]]},"511":{"position":[[0,8]]},"587":{"position":[[7,9]]},"647":{"position":[[0,10]]},"677":{"position":[[14,8]]},"685":{"position":[[11,8]]}}}],["score",{"_index":106,"t":{"521":{"position":[[11,6]]},"529":{"position":[[7,6]]}}}],["screen",{"_index":120,"t":{"543":{"position":[[0,6]]},"561":{"position":[[0,6]]}}}],["secondari",{"_index":128,"t":{"557":{"position":[[0,9]]}}}],["secur",{"_index":196,"t":{"667":{"position":[[0,8]]}}}],["sensor",{"_index":138,"t":{"583":{"position":[[0,6]]},"605":{"position":[[0,6]]},"631":{"position":[[31,7]]},"711":{"position":[[23,7]]},"713":{"position":[[9,6]]},"731":{"position":[[0,6]]}}}],["sensor'",{"_index":214,"t":{"703":{"position":[[29,8]]}}}],["server",{"_index":166,"t":{"631":{"position":[[17,6]]}}}],["share",{"_index":70,"t":{"419":{"position":[[17,5]]},"461":{"position":[[17,5]]},"503":{"position":[[17,5]]}}}],["signific",{"_index":20,"t":{"78":{"position":[[0,11]]},"525":{"position":[[0,11]]}}}],["skill",{"_index":88,"t":{"449":{"position":[[4,6]]}}}],["sleep",{"_index":102,"t":{"519":{"position":[[0,5]]},"539":{"position":[[0,5]]},"551":{"position":[[10,5]]}}}],["sm",{"_index":121,"t":{"545":{"position":[[0,3]]}}}],["specif",{"_index":34,"t":{"115":{"position":[[31,8]]}}}],["stabil",{"_index":0,"t":{"1":{"position":[[0,9]]},"38":{"position":[[0,9]]},"58":{"position":[[0,9]]},"101":{"position":[[6,9]]},"123":{"position":[[14,9]]}}}],["start",{"_index":135,"t":{"575":{"position":[[13,5]]}}}],["step",{"_index":131,"t":{"565":{"position":[[0,4]]}}}],["studi",{"_index":63,"t":{"409":{"position":[[9,5]]},"493":{"position":[[9,5]]},"711":{"position":[[34,7]]}}}],["support",{"_index":184,"t":{"653":{"position":[[25,7]]},"665":{"position":[[12,7]]}}}],["survey",{"_index":62,"t":{"407":{"position":[[21,7]]},"481":{"position":[[5,7]]},"497":{"position":[[21,7]]},"529":{"position":[[0,6]]},"567":{"position":[[0,6]]},"669":{"position":[[5,7]]},"679":{"position":[[21,7]]},"695":{"position":[[0,6]]},"733":{"position":[[0,7]]}}}],["tab",{"_index":222,"t":{"711":{"position":[[42,3]]}}}],["tag",{"_index":159,"t":{"619":{"position":[[0,4]]}}}],["take",{"_index":97,"t":{"481":{"position":[[0,4]]},"669":{"position":[[0,4]]}}}],["target",{"_index":89,"t":{"451":{"position":[[4,6]]},"459":{"position":[[10,6]]}}}],["task",{"_index":174,"t":{"647":{"position":[[11,5]]}}}],["team",{"_index":208,"t":{"691":{"position":[[5,4]]}}}],["test",{"_index":41,"t":{"163":{"position":[[32,5]]},"633":{"position":[[0,7]]}}}],["time",{"_index":167,"t":{"637":{"position":[[8,4]]}}}],["tip",{"_index":65,"t":{"413":{"position":[[9,3]]},"485":{"position":[[7,3]]},"495":{"position":[[9,3]]},"687":{"position":[[21,4]]},"705":{"position":[[20,5]]}}}],["train",{"_index":203,"t":{"683":{"position":[[0,8]]}}}],["transform",{"_index":229,"t":{"737":{"position":[[15,15]]}}}],["trick",{"_index":217,"t":{"705":{"position":[[30,6]]}}}],["trip",{"_index":110,"t":{"527":{"position":[[0,5]]},"569":{"position":[[0,4]]},"571":{"position":[[0,4]]}}}],["troubleshoot",{"_index":170,"t":{"639":{"position":[[0,15]]},"715":{"position":[[0,15]]}}}],["tutori",{"_index":211,"t":{"699":{"position":[[13,8]]}}}],["type",{"_index":147,"t":{"605":{"position":[[7,5]]},"609":{"position":[[9,5]]},"731":{"position":[[7,5]]}}}],["ui",{"_index":21,"t":{"78":{"position":[[39,2]]}}}],["updat",{"_index":14,"t":{"47":{"position":[[23,7]]},"66":{"position":[[33,7]]},"101":{"position":[[16,7]]},"107":{"position":[[25,7]]},"699":{"position":[[5,7]]}}}],["upgrad",{"_index":3,"t":{"1":{"position":[[27,8]]},"26":{"position":[[16,8]]}}}],["us",{"_index":16,"t":{"54":{"position":[[8,3]]},"115":{"position":[[40,3]]},"149":{"position":[[8,3]]},"395":{"position":[[6,5]]},"597":{"position":[[0,5]]},"721":{"position":[[22,3]]},"737":{"position":[[0,5]]}}}],["usag",{"_index":108,"t":{"523":{"position":[[9,5]]},"681":{"position":[[31,5]]}}}],["user",{"_index":8,"t":{"26":{"position":[[0,4]]},"141":{"position":[[5,4]]},"415":{"position":[[18,4]]},"419":{"position":[[9,4]]},"461":{"position":[[9,4]]},"487":{"position":[[30,5]]},"499":{"position":[[18,4]]},"503":{"position":[[9,4]]},"711":{"position":[[0,5]]}}}],["via",{"_index":153,"t":{"613":{"position":[[10,3]]}}}],["view",{"_index":219,"t":{"709":{"position":[[0,4]]}}}],["visual",{"_index":18,"t":{"66":{"position":[[7,14]]},"107":{"position":[[0,13]]},"595":{"position":[[18,14]]},"697":{"position":[[0,9]]}}}],["vs",{"_index":221,"t":{"711":{"position":[[6,2],[20,2],[31,2]]},"721":{"position":[[9,3]]}}}],["wearabl",{"_index":218,"t":{"707":{"position":[[0,9]]}}}],["webinar",{"_index":84,"t":{"439":{"position":[[0,8]]}}}],["who'",{"_index":49,"t":{"395":{"position":[[0,5]]}}}],["work",{"_index":47,"t":{"391":{"position":[[23,5]]},"599":{"position":[[30,5]]},"645":{"position":[[17,5]]},"701":{"position":[[26,5]]}}}],["write",{"_index":186,"t":{"657":{"position":[[0,7]]}}}]],"pipeline":["stemmer"]}},{"documents":[{"i":3,"t":"Improvements","u":"/blog/2020/08/25/","h":"#improvements","p":1},{"i":4,"t":"Infrastructure Upgrades","u":"/blog/2020/08/25/","h":"#infrastructure-upgrades","p":1},{"i":6,"t":"Bug Fixes","u":"/blog/2020/08/25/","h":"#bug-fixes","p":1},{"i":10,"t":"Features","u":"/blog/2020/10/05/","h":"#features","p":8},{"i":11,"t":"Brand new user experience","u":"/blog/2020/10/05/","h":"#brand-new-user-experience","p":8},{"i":13,"t":"New activities and interventions","u":"/blog/2020/10/05/","h":"#new-activities-and-interventions","p":8},{"i":15,"t":"Visual data dashboard","u":"/blog/2020/10/05/","h":"#visual-data-dashboard","p":8},{"i":17,"t":"Wearables support","u":"/blog/2020/10/05/","h":"#wearables-support","p":8},{"i":19,"t":"Improvements","u":"/blog/2020/10/05/","h":"#improvements","p":8},{"i":20,"t":"Push notifications","u":"/blog/2020/10/05/","h":"#push-notifications","p":8},{"i":22,"t":"Database improvements","u":"/blog/2020/10/05/","h":"#database-improvements","p":8},{"i":24,"t":"Bug Fixes","u":"/blog/2020/10/05/","h":"#bug-fixes","p":8},{"i":28,"t":"Features","u":"/blog/2020/10/15/","h":"#features","p":26},{"i":29,"t":"Updated management interface","u":"/blog/2020/10/15/","h":"#updated-management-interface","p":26},{"i":31,"t":"Self-hosted deployment support","u":"/blog/2020/10/15/","h":"#self-hosted-deployment-support","p":26},{"i":33,"t":"Improvements","u":"/blog/2020/10/15/","h":"#improvements","p":26},{"i":34,"t":"Database improvements","u":"/blog/2020/10/15/","h":"#database-improvements","p":26},{"i":36,"t":"Bug Fixes","u":"/blog/2020/10/15/","h":"#bug-fixes","p":26},{"i":40,"t":"Improvements","u":"/blog/2020/11/05/","h":"#improvements","p":38},{"i":41,"t":"Survey Slider Options & Description","u":"/blog/2020/11/05/","h":"#survey-slider-options--description","p":38},{"i":43,"t":"Upload Guided Meditation Audio","u":"/blog/2020/11/05/","h":"#upload-guided-meditation-audio","p":38},{"i":45,"t":"Bug Fixes","u":"/blog/2020/11/05/","h":"#bug-fixes","p":38},{"i":49,"t":"Features","u":"/blog/2020/10/23/","h":"#features","p":47},{"i":50,"t":"Customizable Activities","u":"/blog/2020/10/23/","h":"#customizable-activities","p":47},{"i":52,"t":"Bug Fixes","u":"/blog/2020/10/23/","h":"#bug-fixes","p":47},{"i":56,"t":"Bug Fixes","u":"/blog/2020/11/06/","h":"#bug-fixes","p":54},{"i":60,"t":"Improvements","u":"/blog/2021/01/11/","h":"#improvements","p":58},{"i":62,"t":"Analytics API","u":"/blog/2021/01/11/","h":"#analytics-api","p":58},{"i":64,"t":"Bug Fixes","u":"/blog/2021/01/11/","h":"#bug-fixes","p":58},{"i":68,"t":"Features","u":"/blog/2020/12/01/","h":"#features","p":66},{"i":69,"t":"Cortex & Enhanced Visualizations","u":"/blog/2020/12/01/","h":"#cortex--enhanced-visualizations","p":66},{"i":71,"t":"Improvements","u":"/blog/2020/12/01/","h":"#improvements","p":66},{"i":72,"t":"Localization & Internationalization","u":"/blog/2020/12/01/","h":"#localization--internationalization","p":66},{"i":74,"t":"Activities & Surveys","u":"/blog/2020/12/01/","h":"#activities--surveys","p":66},{"i":76,"t":"Bug Fixes","u":"/blog/2020/12/01/","h":"#bug-fixes","p":66},{"i":80,"t":"Frontend","u":"/blog/2021/04/22/","h":"#frontend","p":78},{"i":82,"t":"Features","u":"/blog/2021/04/22/","h":"#features","p":78},{"i":84,"t":"Improvements","u":"/blog/2021/04/22/","h":"#improvements","p":78},{"i":86,"t":"Bug Fixes","u":"/blog/2021/04/22/","h":"#bug-fixes","p":78},{"i":88,"t":"Backend","u":"/blog/2021/04/22/","h":"#backend","p":78},{"i":89,"t":"Features","u":"/blog/2021/04/22/","h":"#features-1","p":78},{"i":91,"t":"Bug Fixes","u":"/blog/2021/04/22/","h":"#bug-fixes-1","p":78},{"i":93,"t":"Native Core (iOS & Android)","u":"/blog/2021/04/22/","h":"#native-core-ios--android","p":78},{"i":95,"t":"Features","u":"/blog/2021/04/22/","h":"#features-2","p":78},{"i":97,"t":"Bug Fixes","u":"/blog/2021/04/22/","h":"#bug-fixes-2","p":78},{"i":103,"t":"Updates","u":"/blog/2021/08/09/","h":"#updates","p":101},{"i":105,"t":"Bug Fixes","u":"/blog/2021/08/09/","h":"#bug-fixes","p":101},{"i":109,"t":"Updates","u":"/blog/2021/08/25/","h":"#updates","p":107},{"i":111,"t":"Bug Fixes","u":"/blog/2021/08/25/","h":"#bug-fixes","p":107},{"i":117,"t":"New Features","u":"/blog/2021/11/22/","h":"","p":115},{"i":119,"t":"Updates","u":"/blog/2021/11/22/","h":"","p":115},{"i":121,"t":"Bux Fixes","u":"/blog/2021/11/22/","h":"","p":115},{"i":125,"t":"New Features","u":"/blog/2021/12/16/","h":"","p":123},{"i":127,"t":"Updates","u":"/blog/2021/12/16/","h":"","p":123},{"i":129,"t":"Bux Fixes","u":"/blog/2021/12/16/","h":"","p":123},{"i":133,"t":"Features & Improvements","u":"/blog/2022/03/07/","h":"#features--improvements","p":131},{"i":137,"t":"New features and fixes for cortex","u":"/blog/2022/03/22/","h":"#new-features-and-fixes-for-cortex","p":135},{"i":139,"t":"Details:","u":"/blog/2022/03/22/","h":"#details","p":135},{"i":143,"t":"Frontend","u":"/blog/2022/1/11/","h":"","p":141},{"i":145,"t":"Known Issues","u":"/blog/2022/1/11/","h":"#known-issues","p":141},{"i":147,"t":"Backend","u":"/blog/2022/1/11/","h":"","p":141},{"i":151,"t":"Features","u":"/blog/2020/12/17/","h":"#features","p":149},{"i":152,"t":"App Toolbar","u":"/blog/2020/12/17/","h":"#app-toolbar","p":149},{"i":154,"t":"Study Management","u":"/blog/2020/12/17/","h":"#study-management","p":149},{"i":156,"t":"Real-time Event Subscription API","u":"/blog/2020/12/17/","h":"#real-time-event-subscription-api","p":149},{"i":158,"t":"Improvements","u":"/blog/2020/12/17/","h":"#improvements","p":149},{"i":159,"t":"Miscellaneous","u":"/blog/2020/12/17/","h":"#miscellaneous","p":149},{"i":161,"t":"Bug Fixes","u":"/blog/2020/12/17/","h":"#bug-fixes","p":149},{"i":165,"t":"Features","u":"/blog/2021/02/12/","h":"#features","p":163},{"i":166,"t":"Patient Profile UI","u":"/blog/2021/02/12/","h":"#patient-profile-ui","p":163},{"i":168,"t":"Pop The Bubbles & Balloon Risk","u":"/blog/2021/02/12/","h":"#pop-the-bubbles--balloon-risk","p":163},{"i":170,"t":"Improvements","u":"/blog/2021/02/12/","h":"#improvements","p":163},{"i":171,"t":"Improved Native Apps","u":"/blog/2021/02/12/","h":"#improved-native-apps","p":163},{"i":173,"t":"Improved Native Apps","u":"/blog/2021/02/12/","h":"#improved-native-apps-1","p":163},{"i":175,"t":"Hardened Security Requirements","u":"/blog/2021/02/12/","h":"#hardened-security-requirements","p":163},{"i":177,"t":"Bug Fixes","u":"/blog/2021/02/12/","h":"#bug-fixes","p":163},{"i":181,"t":"Features & Improvements","u":"/blog/2022/04/23/","h":"#features--improvements","p":179},{"i":183,"t":"Bug Fixes","u":"/blog/2022/04/23/","h":"#bug-fixes","p":179},{"i":187,"t":"Features & Improvements","u":"/blog/2022/2/15/","h":"#features--improvements","p":185},{"i":189,"t":"Bug Fixes","u":"/blog/2022/2/15/","h":"#bug-fixes","p":185},{"i":193,"t":"Minor Stability Updates and Bug Fixes","u":"/blog/page/10","h":"","p":192},{"i":195,"t":"Updates","u":"/blog/page/10","h":"#updates","p":192},{"i":197,"t":"Bug Fixes","u":"/blog/page/10","h":"#bug-fixes","p":192},{"i":200,"t":"Significant Performance Improvements & UI Overhaul","u":"/blog/page/11","h":"","p":199},{"i":202,"t":"Frontend","u":"/blog/page/11","h":"#frontend","p":199},{"i":204,"t":"Features","u":"/blog/page/11","h":"#features","p":199},{"i":206,"t":"Improvements","u":"/blog/page/11","h":"#improvements","p":199},{"i":208,"t":"Bug Fixes","u":"/blog/page/11","h":"#bug-fixes","p":199},{"i":210,"t":"Backend","u":"/blog/page/11","h":"#backend","p":199},{"i":211,"t":"Features","u":"/blog/page/11","h":"#features-1","p":199},{"i":213,"t":"Bug Fixes","u":"/blog/page/11","h":"#bug-fixes-1","p":199},{"i":215,"t":"Native Core (iOS & Android)","u":"/blog/page/11","h":"#native-core-ios--android","p":199},{"i":217,"t":"Features","u":"/blog/page/11","h":"#features-2","p":199},{"i":219,"t":"Bug Fixes","u":"/blog/page/11","h":"#bug-fixes-2","p":199},{"i":222,"t":"Documentation Overhaul","u":"/blog/page/12","h":"","p":221},{"i":225,"t":"Stability & Performance Improvements","u":"/blog/page/14","h":"","p":224},{"i":227,"t":"Improvements","u":"/blog/page/14","h":"#improvements","p":224},{"i":229,"t":"Analytics API","u":"/blog/page/14","h":"#analytics-api","p":224},{"i":231,"t":"Bug Fixes","u":"/blog/page/14","h":"#bug-fixes","p":224},{"i":234,"t":"Patient Profile & New Cognitive Tests","u":"/blog/page/13","h":"","p":233},{"i":236,"t":"Features","u":"/blog/page/13","h":"#features","p":233},{"i":237,"t":"Patient Profile UI","u":"/blog/page/13","h":"#patient-profile-ui","p":233},{"i":239,"t":"Pop The Bubbles & Balloon Risk","u":"/blog/page/13","h":"#pop-the-bubbles--balloon-risk","p":233},{"i":241,"t":"Improvements","u":"/blog/page/13","h":"#improvements","p":233},{"i":242,"t":"Improved Native Apps","u":"/blog/page/13","h":"#improved-native-apps","p":233},{"i":244,"t":"Improved Native Apps","u":"/blog/page/13","h":"#improved-native-apps-1","p":233},{"i":246,"t":"Hardened Security Requirements","u":"/blog/page/13","h":"#hardened-security-requirements","p":233},{"i":248,"t":"Bug Fixes","u":"/blog/page/13","h":"#bug-fixes","p":233},{"i":251,"t":"Cortex Visualizations & Activity Updates","u":"/blog/page/16","h":"","p":250},{"i":253,"t":"Features","u":"/blog/page/16","h":"#features","p":250},{"i":254,"t":"Cortex & Enhanced Visualizations","u":"/blog/page/16","h":"#cortex--enhanced-visualizations","p":250},{"i":256,"t":"Improvements","u":"/blog/page/16","h":"#improvements","p":250},{"i":257,"t":"Localization & Internationalization","u":"/blog/page/16","h":"#localization--internationalization","p":250},{"i":259,"t":"Activities & Surveys","u":"/blog/page/16","h":"#activities--surveys","p":250},{"i":261,"t":"Bug Fixes","u":"/blog/page/16","h":"#bug-fixes","p":250},{"i":264,"t":"Ease of Use Improvements","u":"/blog/page/15","h":"","p":263},{"i":266,"t":"Features","u":"/blog/page/15","h":"#features","p":263},{"i":267,"t":"App Toolbar","u":"/blog/page/15","h":"#app-toolbar","p":263},{"i":269,"t":"Study Management","u":"/blog/page/15","h":"#study-management","p":263},{"i":271,"t":"Real-time Event Subscription API","u":"/blog/page/15","h":"#real-time-event-subscription-api","p":263},{"i":273,"t":"Improvements","u":"/blog/page/15","h":"#improvements","p":263},{"i":274,"t":"Miscellaneous","u":"/blog/page/15","h":"#miscellaneous","p":263},{"i":276,"t":"Bug Fixes","u":"/blog/page/15","h":"#bug-fixes","p":263},{"i":279,"t":"Ease of Use Improvements","u":"/blog/page/17","h":"","p":278},{"i":281,"t":"Bug Fixes","u":"/blog/page/17","h":"#bug-fixes","p":278},{"i":285,"t":"New features and fixes for cortex","u":"/blog/page/2","h":"#new-features-and-fixes-for-cortex","p":283},{"i":287,"t":"Details:","u":"/blog/page/2","h":"#details","p":283},{"i":290,"t":"General Availability of mindLAMP 2","u":"/blog/page/21","h":"","p":289},{"i":292,"t":"Features","u":"/blog/page/21","h":"#features","p":289},{"i":293,"t":"Brand new user experience","u":"/blog/page/21","h":"#brand-new-user-experience","p":289},{"i":295,"t":"New activities and interventions","u":"/blog/page/21","h":"#new-activities-and-interventions","p":289},{"i":297,"t":"Visual data dashboard","u":"/blog/page/21","h":"#visual-data-dashboard","p":289},{"i":299,"t":"Wearables support","u":"/blog/page/21","h":"#wearables-support","p":289},{"i":301,"t":"Improvements","u":"/blog/page/21","h":"#improvements","p":289},{"i":302,"t":"Push notifications","u":"/blog/page/21","h":"#push-notifications","p":289},{"i":304,"t":"Database improvements","u":"/blog/page/21","h":"#database-improvements","p":289},{"i":306,"t":"Bug Fixes","u":"/blog/page/21","h":"#bug-fixes","p":289},{"i":309,"t":"Stability & Performance Improvements","u":"/blog/page/18","h":"","p":308},{"i":311,"t":"Improvements","u":"/blog/page/18","h":"#improvements","p":308},{"i":312,"t":"Survey Slider Options & Description","u":"/blog/page/18","h":"#survey-slider-options--description","p":308},{"i":314,"t":"Upload Guided Meditation Audio","u":"/blog/page/18","h":"#upload-guided-meditation-audio","p":308},{"i":316,"t":"Bug Fixes","u":"/blog/page/18","h":"#bug-fixes","p":308},{"i":319,"t":"Clinical Customization Updates","u":"/blog/page/19","h":"","p":318},{"i":321,"t":"Features","u":"/blog/page/19","h":"#features","p":318},{"i":322,"t":"Customizable Activities","u":"/blog/page/19","h":"#customizable-activities","p":318},{"i":324,"t":"Bug Fixes","u":"/blog/page/19","h":"#bug-fixes","p":318},{"i":327,"t":"User Experience Upgrades","u":"/blog/page/20","h":"","p":326},{"i":329,"t":"Features","u":"/blog/page/20","h":"#features","p":326},{"i":330,"t":"Updated management interface","u":"/blog/page/20","h":"#updated-management-interface","p":326},{"i":332,"t":"Self-hosted deployment support","u":"/blog/page/20","h":"#self-hosted-deployment-support","p":326},{"i":334,"t":"Improvements","u":"/blog/page/20","h":"#improvements","p":326},{"i":335,"t":"Database improvements","u":"/blog/page/20","h":"#database-improvements","p":326},{"i":337,"t":"Bug Fixes","u":"/blog/page/20","h":"#bug-fixes","p":326},{"i":341,"t":"Features & Improvements","u":"/blog/page/3","h":"#features--improvements","p":339},{"i":344,"t":"Stability & Infrastructure Upgrades","u":"/blog/page/22","h":"","p":343},{"i":346,"t":"Improvements","u":"/blog/page/22","h":"#improvements","p":343},{"i":347,"t":"Infrastructure Upgrades","u":"/blog/page/22","h":"#infrastructure-upgrades","p":343},{"i":349,"t":"Bug Fixes","u":"/blog/page/22","h":"#bug-fixes","p":343},{"i":353,"t":"Features & Improvements","u":"/blog/page/4","h":"#features--improvements","p":351},{"i":355,"t":"Bug Fixes","u":"/blog/page/4","h":"#bug-fixes","p":351},{"i":358,"t":"2022 User Interface Improvements","u":"/blog/page/5","h":"","p":357},{"i":361,"t":"Known Issues","u":"/blog/page/5","h":"#known-issues","p":357},{"i":363,"t":"Backend","u":"/blog/page/5","h":"","p":357},{"i":366,"t":"New features, stability fixes, and improvements","u":"/blog/page/6","h":"","p":365},{"i":369,"t":"Updates","u":"/blog/page/6","h":"","p":365},{"i":371,"t":"Bux Fixes","u":"/blog/page/6","h":"","p":365},{"i":374,"t":"New, fully functional Clinical-specific use for mindLAMP!","u":"/blog/page/7","h":"","p":373},{"i":377,"t":"Updates","u":"/blog/page/7","h":"","p":373},{"i":379,"t":"Bux Fixes","u":"/blog/page/7","h":"","p":373},{"i":382,"t":"Scheduled Routine mindLAMP AWS Maintenance","u":"/blog/page/8","h":"","p":381},{"i":385,"t":"Visualization & Activity Updates","u":"/blog/page/9","h":"","p":384},{"i":387,"t":"Updates","u":"/blog/page/9","h":"#updates","p":384},{"i":389,"t":"Bug Fixes","u":"/blog/page/9","h":"#bug-fixes","p":384}],"index":{"version":"2.3.9","fields":["t"],"fieldVectors":[["t/3",[0,1.963]],["t/4",[1,4.131,2,3.865]],["t/6",[3,1.711,4,1.516]],["t/10",[5,2.355]],["t/11",[6,3.263,7,2.089,8,2.811,9,3.004]],["t/13",[7,2.419,10,2.688,11,3.778]],["t/15",[12,2.927,13,3.778,14,3.778]],["t/17",[15,4.487,16,3.865]],["t/19",[0,1.963]],["t/20",[17,4.487,18,4.487]],["t/22",[0,1.595,19,3.865]],["t/24",[3,1.711,4,1.516]],["t/28",[5,2.355]],["t/29",[20,2.213,21,3.255,22,3.478]],["t/31",[16,2.811,23,3.263,24,3.263,25,3.263]],["t/33",[0,1.963]],["t/34",[0,1.595,19,3.865]],["t/36",[3,1.711,4,1.516]],["t/40",[0,1.963]],["t/41",[26,2.473,27,2.871,28,2.871,29,1.327,30,2.871]],["t/43",[31,3.263,32,3.263,33,3.263,34,3.263]],["t/45",[3,1.711,4,1.516]],["t/49",[5,2.355]],["t/50",[10,3.192,35,4.487]],["t/52",[3,1.711,4,1.516]],["t/56",[3,1.711,4,1.516]],["t/60",[0,1.963]],["t/62",[36,4.487,37,3.865]],["t/64",[3,1.711,4,1.516]],["t/68",[5,2.355]],["t/69",[12,2.528,29,1.508,38,2.656,39,3.263]],["t/71",[0,1.963]],["t/72",[29,1.746,40,3.778,41,3.778]],["t/74",[10,2.688,26,3.255,29,1.746]],["t/76",[3,1.711,4,1.516]],["t/80",[42,5.084]],["t/82",[5,2.355]],["t/84",[0,1.963]],["t/86",[3,1.711,4,1.516]],["t/88",[43,4.757]],["t/89",[5,2.355]],["t/91",[3,1.711,4,1.516]],["t/93",[29,1.327,44,2.224,45,2.871,46,2.871,47,2.871]],["t/95",[5,2.355]],["t/97",[3,1.711,4,1.516]],["t/103",[20,3.234]],["t/105",[3,1.711,4,1.516]],["t/109",[20,3.234]],["t/111",[3,1.711,4,1.516]],["t/117",[5,1.913,7,2.873]],["t/119",[20,3.234]],["t/121",[4,1.516,48,3.865]],["t/125",[5,1.913,7,2.873]],["t/127",[20,3.234]],["t/129",[4,1.516,48,3.865]],["t/133",[0,1.343,5,1.611,29,1.746]],["t/137",[4,1.102,5,1.391,7,2.089,38,2.656]],["t/139",[49,5.522]],["t/143",[42,5.084]],["t/145",[50,4.487,51,4.487]],["t/147",[43,4.757]],["t/151",[5,2.355]],["t/152",[52,3.476,53,4.487]],["t/154",[21,3.865,54,4.487]],["t/156",[37,2.473,55,2.871,56,2.871,57,2.871,58,2.871]],["t/158",[0,1.963]],["t/159",[59,5.522]],["t/161",[3,1.711,4,1.516]],["t/165",[5,2.355]],["t/166",[60,3.478,61,3.478,62,3.478]],["t/168",[29,1.327,63,2.871,64,2.871,65,2.871,66,2.871]],["t/170",[0,1.963]],["t/171",[0,1.343,44,2.927,52,2.927]],["t/173",[0,1.343,44,2.927,52,2.927]],["t/175",[67,3.778,68,3.778,69,3.778]],["t/177",[3,1.711,4,1.516]],["t/181",[0,1.343,5,1.611,29,1.746]],["t/183",[3,1.711,4,1.516]],["t/187",[0,1.343,5,1.611,29,1.746]],["t/189",[3,1.711,4,1.516]],["t/193",[3,1.095,4,0.97,20,1.682,70,3.217,71,2.337]],["t/195",[20,3.234]],["t/197",[3,1.711,4,1.516]],["t/200",[0,0.911,29,1.184,62,2.36,72,2.872,73,2.36,74,2.563]],["t/202",[42,5.084]],["t/204",[5,2.355]],["t/206",[0,1.963]],["t/208",[3,1.711,4,1.516]],["t/210",[43,4.757]],["t/211",[5,2.355]],["t/213",[3,1.711,4,1.516]],["t/215",[29,1.327,44,2.224,45,2.871,46,2.871,47,2.871]],["t/217",[5,2.355]],["t/219",[3,1.711,4,1.516]],["t/222",[74,4.487,75,5.027]],["t/225",[0,1.16,29,1.508,71,2.656,73,3.004]],["t/227",[0,1.963]],["t/229",[36,4.487,37,3.865]],["t/231",[3,1.711,4,1.516]],["t/234",[7,1.641,29,1.184,60,2.36,61,2.36,76,2.872,77,2.872]],["t/236",[5,2.355]],["t/237",[60,3.478,61,3.478,62,3.478]],["t/239",[29,1.327,63,2.871,64,2.871,65,2.871,66,2.871]],["t/241",[0,1.963]],["t/242",[0,1.343,44,2.927,52,2.927]],["t/244",[0,1.343,44,2.927,52,2.927]],["t/246",[67,3.778,68,3.778,69,3.778]],["t/248",[3,1.711,4,1.516]],["t/251",[10,2.043,12,2.224,20,1.682,29,1.327,38,2.337]],["t/253",[5,2.355]],["t/254",[12,2.528,29,1.508,38,2.656,39,3.263]],["t/256",[0,1.963]],["t/257",[29,1.746,40,3.778,41,3.778]],["t/259",[10,2.688,26,3.255,29,1.746]],["t/261",[3,1.711,4,1.516]],["t/264",[0,1.343,78,3.778,79,3.478]],["t/266",[5,2.355]],["t/267",[52,3.476,53,4.487]],["t/269",[21,3.865,54,4.487]],["t/271",[37,2.473,55,2.871,56,2.871,57,2.871,58,2.871]],["t/273",[0,1.963]],["t/274",[59,5.522]],["t/276",[3,1.711,4,1.516]],["t/279",[0,1.343,78,3.778,79,3.478]],["t/281",[3,1.711,4,1.516]],["t/285",[4,1.102,5,1.391,7,2.089,38,2.656]],["t/287",[49,5.522]],["t/290",[80,3.655,81,3.655,82,3.004,83,3.655]],["t/292",[5,2.355]],["t/293",[6,3.263,7,2.089,8,2.811,9,3.004]],["t/295",[7,2.419,10,2.688,11,3.778]],["t/297",[12,2.927,13,3.778,14,3.778]],["t/299",[15,4.487,16,3.865]],["t/301",[0,1.963]],["t/302",[17,4.487,18,4.487]],["t/304",[0,1.595,19,3.865]],["t/306",[3,1.711,4,1.516]],["t/309",[0,1.16,29,1.508,71,2.656,73,3.004]],["t/311",[0,1.963]],["t/312",[26,2.473,27,2.871,28,2.871,29,1.327,30,2.871]],["t/314",[31,3.263,32,3.263,33,3.263,34,3.263]],["t/316",[3,1.711,4,1.516]],["t/319",[20,2.213,84,3.778,85,4.233]],["t/321",[5,2.355]],["t/322",[10,3.192,35,4.487]],["t/324",[3,1.711,4,1.516]],["t/327",[2,3.255,8,3.255,9,3.478]],["t/329",[5,2.355]],["t/330",[20,2.213,21,3.255,22,3.478]],["t/332",[16,2.811,23,3.263,24,3.263,25,3.263]],["t/334",[0,1.963]],["t/335",[0,1.595,19,3.865]],["t/337",[3,1.711,4,1.516]],["t/341",[0,1.343,5,1.611,29,1.746]],["t/344",[1,3.004,2,2.811,29,1.508,71,2.656]],["t/346",[0,1.963]],["t/347",[1,4.131,2,3.865]],["t/349",[3,1.711,4,1.516]],["t/353",[0,1.343,5,1.611,29,1.746]],["t/355",[3,1.711,4,1.516]],["t/358",[0,1.16,8,2.811,22,3.004,86,3.655]],["t/361",[50,4.487,51,4.487]],["t/363",[43,4.757]],["t/366",[0,1.021,4,0.97,5,1.224,7,1.838,71,2.337]],["t/369",[20,3.234]],["t/371",[4,1.516,48,3.865]],["t/374",[7,1.482,79,2.132,82,2.132,84,2.315,87,2.594,88,2.594,89,2.594]],["t/377",[20,3.234]],["t/379",[4,1.516,48,3.865]],["t/382",[82,2.643,90,3.217,91,3.217,92,3.217,93,3.217]],["t/385",[10,2.322,12,2.528,20,1.911,29,1.508]],["t/387",[20,3.234]],["t/389",[3,1.711,4,1.516]]],"invertedIndex":[["",{"_index":29,"t":{"41":{"position":[[22,1]]},"69":{"position":[[7,1]]},"72":{"position":[[13,1]]},"74":{"position":[[11,1]]},"93":{"position":[[17,1]]},"133":{"position":[[9,1]]},"168":{"position":[[16,1]]},"181":{"position":[[9,1]]},"187":{"position":[[9,1]]},"200":{"position":[[37,1]]},"215":{"position":[[17,1]]},"225":{"position":[[10,1]]},"234":{"position":[[16,1]]},"239":{"position":[[16,1]]},"251":{"position":[[22,1]]},"254":{"position":[[7,1]]},"257":{"position":[[13,1]]},"259":{"position":[[11,1]]},"309":{"position":[[10,1]]},"312":{"position":[[22,1]]},"341":{"position":[[9,1]]},"344":{"position":[[10,1]]},"353":{"position":[[9,1]]},"385":{"position":[[14,1]]}}}],["2",{"_index":83,"t":{"290":{"position":[[33,1]]}}}],["2022",{"_index":86,"t":{"358":{"position":[[0,4]]}}}],["activ",{"_index":10,"t":{"13":{"position":[[4,10]]},"50":{"position":[[13,10]]},"74":{"position":[[0,10]]},"251":{"position":[[24,8]]},"259":{"position":[[0,10]]},"295":{"position":[[4,10]]},"322":{"position":[[13,10]]},"385":{"position":[[16,8]]}}}],["analyt",{"_index":36,"t":{"62":{"position":[[0,9]]},"229":{"position":[[0,9]]}}}],["android",{"_index":47,"t":{"93":{"position":[[19,8]]},"215":{"position":[[19,8]]}}}],["api",{"_index":37,"t":{"62":{"position":[[10,3]]},"156":{"position":[[29,3]]},"229":{"position":[[10,3]]},"271":{"position":[[29,3]]}}}],["app",{"_index":52,"t":{"152":{"position":[[0,3]]},"171":{"position":[[16,4]]},"173":{"position":[[16,4]]},"242":{"position":[[16,4]]},"244":{"position":[[16,4]]},"267":{"position":[[0,3]]}}}],["audio",{"_index":34,"t":{"43":{"position":[[25,5]]},"314":{"position":[[25,5]]}}}],["avail",{"_index":81,"t":{"290":{"position":[[8,12]]}}}],["aw",{"_index":92,"t":{"382":{"position":[[27,3]]}}}],["backend",{"_index":43,"t":{"88":{"position":[[0,7]]},"147":{"position":[[0,7]]},"210":{"position":[[0,7]]},"363":{"position":[[0,7]]}}}],["balloon",{"_index":65,"t":{"168":{"position":[[18,7]]},"239":{"position":[[18,7]]}}}],["brand",{"_index":6,"t":{"11":{"position":[[0,5]]},"293":{"position":[[0,5]]}}}],["bubbl",{"_index":64,"t":{"168":{"position":[[8,7]]},"239":{"position":[[8,7]]}}}],["bug",{"_index":3,"t":{"6":{"position":[[0,3]]},"24":{"position":[[0,3]]},"36":{"position":[[0,3]]},"45":{"position":[[0,3]]},"52":{"position":[[0,3]]},"56":{"position":[[0,3]]},"64":{"position":[[0,3]]},"76":{"position":[[0,3]]},"86":{"position":[[0,3]]},"91":{"position":[[0,3]]},"97":{"position":[[0,3]]},"105":{"position":[[0,3]]},"111":{"position":[[0,3]]},"161":{"position":[[0,3]]},"177":{"position":[[0,3]]},"183":{"position":[[0,3]]},"189":{"position":[[0,3]]},"193":{"position":[[28,3]]},"197":{"position":[[0,3]]},"208":{"position":[[0,3]]},"213":{"position":[[0,3]]},"219":{"position":[[0,3]]},"231":{"position":[[0,3]]},"248":{"position":[[0,3]]},"261":{"position":[[0,3]]},"276":{"position":[[0,3]]},"281":{"position":[[0,3]]},"306":{"position":[[0,3]]},"316":{"position":[[0,3]]},"324":{"position":[[0,3]]},"337":{"position":[[0,3]]},"349":{"position":[[0,3]]},"355":{"position":[[0,3]]},"389":{"position":[[0,3]]}}}],["bux",{"_index":48,"t":{"121":{"position":[[0,3]]},"129":{"position":[[0,3]]},"371":{"position":[[0,3]]},"379":{"position":[[0,3]]}}}],["clinic",{"_index":84,"t":{"319":{"position":[[0,8]]},"374":{"position":[[22,8]]}}}],["cognit",{"_index":76,"t":{"234":{"position":[[22,9]]}}}],["core",{"_index":45,"t":{"93":{"position":[[7,4]]},"215":{"position":[[7,4]]}}}],["cortex",{"_index":38,"t":{"69":{"position":[[0,6]]},"137":{"position":[[27,6]]},"251":{"position":[[0,6]]},"254":{"position":[[0,6]]},"285":{"position":[[27,6]]}}}],["custom",{"_index":85,"t":{"319":{"position":[[9,13]]}}}],["customiz",{"_index":35,"t":{"50":{"position":[[0,12]]},"322":{"position":[[0,12]]}}}],["dashboard",{"_index":14,"t":{"15":{"position":[[12,9]]},"297":{"position":[[12,9]]}}}],["data",{"_index":13,"t":{"15":{"position":[[7,4]]},"297":{"position":[[7,4]]}}}],["databas",{"_index":19,"t":{"22":{"position":[[0,8]]},"34":{"position":[[0,8]]},"304":{"position":[[0,8]]},"335":{"position":[[0,8]]}}}],["deploy",{"_index":25,"t":{"31":{"position":[[12,10]]},"332":{"position":[[12,10]]}}}],["descript",{"_index":30,"t":{"41":{"position":[[24,11]]},"312":{"position":[[24,11]]}}}],["detail",{"_index":49,"t":{"139":{"position":[[0,8]]},"287":{"position":[[0,8]]}}}],["document",{"_index":75,"t":{"222":{"position":[[0,13]]}}}],["eas",{"_index":78,"t":{"264":{"position":[[0,4]]},"279":{"position":[[0,4]]}}}],["enhanc",{"_index":39,"t":{"69":{"position":[[9,8]]},"254":{"position":[[9,8]]}}}],["event",{"_index":57,"t":{"156":{"position":[[10,5]]},"271":{"position":[[10,5]]}}}],["experi",{"_index":9,"t":{"11":{"position":[[15,10]]},"293":{"position":[[15,10]]},"327":{"position":[[5,10]]}}}],["featur",{"_index":5,"t":{"10":{"position":[[0,8]]},"28":{"position":[[0,8]]},"49":{"position":[[0,8]]},"68":{"position":[[0,8]]},"82":{"position":[[0,8]]},"89":{"position":[[0,8]]},"95":{"position":[[0,8]]},"117":{"position":[[4,8]]},"125":{"position":[[4,8]]},"133":{"position":[[0,8]]},"137":{"position":[[4,8]]},"151":{"position":[[0,8]]},"165":{"position":[[0,8]]},"181":{"position":[[0,8]]},"187":{"position":[[0,8]]},"204":{"position":[[0,8]]},"211":{"position":[[0,8]]},"217":{"position":[[0,8]]},"236":{"position":[[0,8]]},"253":{"position":[[0,8]]},"266":{"position":[[0,8]]},"285":{"position":[[4,8]]},"292":{"position":[[0,8]]},"321":{"position":[[0,8]]},"329":{"position":[[0,8]]},"341":{"position":[[0,8]]},"353":{"position":[[0,8]]},"366":{"position":[[4,9]]}}}],["fix",{"_index":4,"t":{"6":{"position":[[4,5]]},"24":{"position":[[4,5]]},"36":{"position":[[4,5]]},"45":{"position":[[4,5]]},"52":{"position":[[4,5]]},"56":{"position":[[4,5]]},"64":{"position":[[4,5]]},"76":{"position":[[4,5]]},"86":{"position":[[4,5]]},"91":{"position":[[4,5]]},"97":{"position":[[4,5]]},"105":{"position":[[4,5]]},"111":{"position":[[4,5]]},"121":{"position":[[4,5]]},"129":{"position":[[4,5]]},"137":{"position":[[17,5]]},"161":{"position":[[4,5]]},"177":{"position":[[4,5]]},"183":{"position":[[4,5]]},"189":{"position":[[4,5]]},"193":{"position":[[32,5]]},"197":{"position":[[4,5]]},"208":{"position":[[4,5]]},"213":{"position":[[4,5]]},"219":{"position":[[4,5]]},"231":{"position":[[4,5]]},"248":{"position":[[4,5]]},"261":{"position":[[4,5]]},"276":{"position":[[4,5]]},"281":{"position":[[4,5]]},"285":{"position":[[17,5]]},"306":{"position":[[4,5]]},"316":{"position":[[4,5]]},"324":{"position":[[4,5]]},"337":{"position":[[4,5]]},"349":{"position":[[4,5]]},"355":{"position":[[4,5]]},"366":{"position":[[24,6]]},"371":{"position":[[4,5]]},"379":{"position":[[4,5]]},"389":{"position":[[4,5]]}}}],["frontend",{"_index":42,"t":{"80":{"position":[[0,8]]},"143":{"position":[[0,8]]},"202":{"position":[[0,8]]}}}],["fulli",{"_index":87,"t":{"374":{"position":[[5,5]]}}}],["function",{"_index":88,"t":{"374":{"position":[[11,10]]}}}],["gener",{"_index":80,"t":{"290":{"position":[[0,7]]}}}],["guid",{"_index":32,"t":{"43":{"position":[[7,6]]},"314":{"position":[[7,6]]}}}],["harden",{"_index":67,"t":{"175":{"position":[[0,8]]},"246":{"position":[[0,8]]}}}],["host",{"_index":24,"t":{"31":{"position":[[5,6]]},"332":{"position":[[5,6]]}}}],["improv",{"_index":0,"t":{"3":{"position":[[0,12]]},"19":{"position":[[0,12]]},"22":{"position":[[9,12]]},"33":{"position":[[0,12]]},"34":{"position":[[9,12]]},"40":{"position":[[0,12]]},"60":{"position":[[0,12]]},"71":{"position":[[0,12]]},"84":{"position":[[0,12]]},"133":{"position":[[11,12]]},"158":{"position":[[0,12]]},"170":{"position":[[0,12]]},"171":{"position":[[0,8]]},"173":{"position":[[0,8]]},"181":{"position":[[11,12]]},"187":{"position":[[11,12]]},"200":{"position":[[24,12]]},"206":{"position":[[0,12]]},"225":{"position":[[24,12]]},"227":{"position":[[0,12]]},"241":{"position":[[0,12]]},"242":{"position":[[0,8]]},"244":{"position":[[0,8]]},"256":{"position":[[0,12]]},"264":{"position":[[12,12]]},"273":{"position":[[0,12]]},"279":{"position":[[12,12]]},"301":{"position":[[0,12]]},"304":{"position":[[9,12]]},"309":{"position":[[24,12]]},"311":{"position":[[0,12]]},"334":{"position":[[0,12]]},"335":{"position":[[9,12]]},"341":{"position":[[11,12]]},"346":{"position":[[0,12]]},"353":{"position":[[11,12]]},"358":{"position":[[20,12]]},"366":{"position":[[35,12]]}}}],["infrastructur",{"_index":1,"t":{"4":{"position":[[0,14]]},"344":{"position":[[12,14]]},"347":{"position":[[0,14]]}}}],["interfac",{"_index":22,"t":{"29":{"position":[[19,9]]},"330":{"position":[[19,9]]},"358":{"position":[[10,9]]}}}],["internation",{"_index":41,"t":{"72":{"position":[[15,20]]},"257":{"position":[[15,20]]}}}],["intervent",{"_index":11,"t":{"13":{"position":[[19,13]]},"295":{"position":[[19,13]]}}}],["io",{"_index":46,"t":{"93":{"position":[[12,4]]},"215":{"position":[[12,4]]}}}],["issu",{"_index":51,"t":{"145":{"position":[[6,6]]},"361":{"position":[[6,6]]}}}],["known",{"_index":50,"t":{"145":{"position":[[0,5]]},"361":{"position":[[0,5]]}}}],["local",{"_index":40,"t":{"72":{"position":[[0,12]]},"257":{"position":[[0,12]]}}}],["mainten",{"_index":93,"t":{"382":{"position":[[31,11]]}}}],["manag",{"_index":21,"t":{"29":{"position":[[8,10]]},"154":{"position":[[6,10]]},"269":{"position":[[6,10]]},"330":{"position":[[8,10]]}}}],["medit",{"_index":33,"t":{"43":{"position":[[14,10]]},"314":{"position":[[14,10]]}}}],["mindlamp",{"_index":82,"t":{"290":{"position":[[24,8]]},"374":{"position":[[48,9]]},"382":{"position":[[18,8]]}}}],["minor",{"_index":70,"t":{"193":{"position":[[0,5]]}}}],["miscellan",{"_index":59,"t":{"159":{"position":[[0,13]]},"274":{"position":[[0,13]]}}}],["nativ",{"_index":44,"t":{"93":{"position":[[0,6]]},"171":{"position":[[9,6]]},"173":{"position":[[9,6]]},"215":{"position":[[0,6]]},"242":{"position":[[9,6]]},"244":{"position":[[9,6]]}}}],["new",{"_index":7,"t":{"11":{"position":[[6,3]]},"13":{"position":[[0,3]]},"117":{"position":[[0,3]]},"125":{"position":[[0,3]]},"137":{"position":[[0,3]]},"234":{"position":[[18,3]]},"285":{"position":[[0,3]]},"293":{"position":[[6,3]]},"295":{"position":[[0,3]]},"366":{"position":[[0,3]]},"374":{"position":[[0,4]]}}}],["notif",{"_index":18,"t":{"20":{"position":[[5,13]]},"302":{"position":[[5,13]]}}}],["option",{"_index":28,"t":{"41":{"position":[[14,7]]},"312":{"position":[[14,7]]}}}],["overhaul",{"_index":74,"t":{"200":{"position":[[42,8]]},"222":{"position":[[14,8]]}}}],["patient",{"_index":60,"t":{"166":{"position":[[0,7]]},"234":{"position":[[0,7]]},"237":{"position":[[0,7]]}}}],["perform",{"_index":73,"t":{"200":{"position":[[12,11]]},"225":{"position":[[12,11]]},"309":{"position":[[12,11]]}}}],["pop",{"_index":63,"t":{"168":{"position":[[0,3]]},"239":{"position":[[0,3]]}}}],["profil",{"_index":61,"t":{"166":{"position":[[8,7]]},"234":{"position":[[8,7]]},"237":{"position":[[8,7]]}}}],["push",{"_index":17,"t":{"20":{"position":[[0,4]]},"302":{"position":[[0,4]]}}}],["real",{"_index":55,"t":{"156":{"position":[[0,4]]},"271":{"position":[[0,4]]}}}],["requir",{"_index":69,"t":{"175":{"position":[[18,12]]},"246":{"position":[[18,12]]}}}],["risk",{"_index":66,"t":{"168":{"position":[[26,4]]},"239":{"position":[[26,4]]}}}],["routin",{"_index":91,"t":{"382":{"position":[[10,7]]}}}],["schedul",{"_index":90,"t":{"382":{"position":[[0,9]]}}}],["secur",{"_index":68,"t":{"175":{"position":[[9,8]]},"246":{"position":[[9,8]]}}}],["self",{"_index":23,"t":{"31":{"position":[[0,4]]},"332":{"position":[[0,4]]}}}],["signific",{"_index":72,"t":{"200":{"position":[[0,11]]}}}],["slider",{"_index":27,"t":{"41":{"position":[[7,6]]},"312":{"position":[[7,6]]}}}],["specif",{"_index":89,"t":{"374":{"position":[[31,8]]}}}],["stabil",{"_index":71,"t":{"193":{"position":[[6,9]]},"225":{"position":[[0,9]]},"309":{"position":[[0,9]]},"344":{"position":[[0,9]]},"366":{"position":[[14,9]]}}}],["studi",{"_index":54,"t":{"154":{"position":[[0,5]]},"269":{"position":[[0,5]]}}}],["subscript",{"_index":58,"t":{"156":{"position":[[16,12]]},"271":{"position":[[16,12]]}}}],["support",{"_index":16,"t":{"17":{"position":[[10,7]]},"31":{"position":[[23,7]]},"299":{"position":[[10,7]]},"332":{"position":[[23,7]]}}}],["survey",{"_index":26,"t":{"41":{"position":[[0,6]]},"74":{"position":[[13,7]]},"259":{"position":[[13,7]]},"312":{"position":[[0,6]]}}}],["test",{"_index":77,"t":{"234":{"position":[[32,5]]}}}],["time",{"_index":56,"t":{"156":{"position":[[5,4]]},"271":{"position":[[5,4]]}}}],["toolbar",{"_index":53,"t":{"152":{"position":[[4,7]]},"267":{"position":[[4,7]]}}}],["ui",{"_index":62,"t":{"166":{"position":[[16,2]]},"200":{"position":[[39,2]]},"237":{"position":[[16,2]]}}}],["updat",{"_index":20,"t":{"29":{"position":[[0,7]]},"103":{"position":[[0,7]]},"109":{"position":[[0,7]]},"119":{"position":[[0,7]]},"127":{"position":[[0,7]]},"193":{"position":[[16,7]]},"195":{"position":[[0,7]]},"251":{"position":[[33,7]]},"319":{"position":[[23,7]]},"330":{"position":[[0,7]]},"369":{"position":[[0,7]]},"377":{"position":[[0,7]]},"385":{"position":[[25,7]]},"387":{"position":[[0,7]]}}}],["upgrad",{"_index":2,"t":{"4":{"position":[[15,8]]},"327":{"position":[[16,8]]},"344":{"position":[[27,8]]},"347":{"position":[[15,8]]}}}],["upload",{"_index":31,"t":{"43":{"position":[[0,6]]},"314":{"position":[[0,6]]}}}],["us",{"_index":79,"t":{"264":{"position":[[8,3]]},"279":{"position":[[8,3]]},"374":{"position":[[40,3]]}}}],["user",{"_index":8,"t":{"11":{"position":[[10,4]]},"293":{"position":[[10,4]]},"327":{"position":[[0,4]]},"358":{"position":[[5,4]]}}}],["visual",{"_index":12,"t":{"15":{"position":[[0,6]]},"69":{"position":[[18,14]]},"251":{"position":[[7,14]]},"254":{"position":[[18,14]]},"297":{"position":[[0,6]]},"385":{"position":[[0,13]]}}}],["wearabl",{"_index":15,"t":{"17":{"position":[[0,9]]},"299":{"position":[[0,9]]}}}]],"pipeline":["stemmer"]}},{"documents":[{"i":1,"t":"Improvements","s":"Stability & Infrastructure Upgrades","u":"/blog/2020/08/25/","p":1},{"i":8,"t":"Features","s":"General Availability of mindLAMP 2","u":"/blog/2020/10/05/","p":8},{"i":26,"t":"Features","s":"User Experience Upgrades","u":"/blog/2020/10/15/","p":26},{"i":38,"t":"Improvements","s":"Stability & Performance Improvements","u":"/blog/2020/11/05/","p":38},{"i":47,"t":"Features","s":"Clinical Customization Updates","u":"/blog/2020/10/23/","p":47},{"i":54,"t":"Bug Fixes","s":"Ease of Use Improvements","u":"/blog/2020/11/06/","p":54},{"i":58,"t":"Improvements","s":"Stability & Performance Improvements","u":"/blog/2021/01/11/","p":58},{"i":66,"t":"Features","s":"Cortex Visualizations & Activity Updates","u":"/blog/2020/12/01/","p":66},{"i":78,"t":"This is a significant update -- please review the bolded disclaimer text!","s":"Significant Performance Improvements & UI Overhaul","u":"/blog/2021/04/22/","p":78},{"i":99,"t":"Welcome to the brand new documentation site!","s":"Documentation Overhaul","u":"/blog/2021/04/01/","p":99},{"i":101,"t":"Updates","s":"Minor Stability Updates and Bug Fixes","u":"/blog/2021/08/09/","p":101},{"i":107,"t":"Updates","s":"Visualization & Activity Updates","u":"/blog/2021/08/25/","p":107},{"i":113,"t":"Hi all,","s":"Scheduled Routine mindLAMP AWS Maintenance","u":"/blog/2021/09/13/","p":113},{"i":115,"t":"mindLAMP now features a variety of new features to support a clinical-only team if there is no need for specialized researcher functions or if a simpler and streamlined UI is preferred. See our documentation here for greater details.","s":"New, fully functional Clinical-specific use for mindLAMP!","u":"/blog/2021/11/22/","p":115},{"i":123,"t":"- Questions created in the survey builder can now be toggled between to have optional or required responses. By default, they will begin as required but can be checked to be optional","s":"New features, stability fixes, and improvements","u":"/blog/2021/12/16/","p":123},{"i":131,"t":"Features & Improvements","s":"","u":"/blog/2022/03/07/","p":131},{"i":135,"t":"New features and fixes for cortex","s":"","u":"/blog/2022/03/22/","p":135},{"i":141,"t":"Server administrators MUST upgrade from2022 versions in the Docker configuration. Please contact us on the forum if there are any questions.","s":"2022 User Interface Improvements","u":"/blog/2022/1/11/","p":141},{"i":149,"t":"Features","s":"Ease of Use Improvements","u":"/blog/2020/12/17/","p":149},{"i":163,"t":"Features","s":"Patient Profile & New Cognitive Tests","u":"/blog/2021/02/12/","p":163},{"i":179,"t":"Features & Improvements","s":"Release 2022.4.23","u":"/blog/2022/04/23/","p":179},{"i":185,"t":"Features & Improvements","s":"","u":"/blog/2022/2/15/","p":185},{"i":191,"t":"Archive","s":"","u":"/blog/archive","p":191},{"i":192,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/10","p":192},{"i":199,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/11","p":199},{"i":221,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/12","p":221},{"i":224,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/14","p":224},{"i":233,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/13","p":233},{"i":250,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/16","p":250},{"i":263,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/15","p":263},{"i":278,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/17","p":278},{"i":283,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/2","p":283},{"i":289,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/21","p":289},{"i":308,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/18","p":308},{"i":318,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/19","p":318},{"i":326,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/20","p":326},{"i":339,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/3","p":339},{"i":343,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/22","p":343},{"i":351,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/4","p":351},{"i":357,"t":"The LAMP Platform documentation.","s":"Frontend","u":"/blog/page/5","p":357},{"i":365,"t":"The LAMP Platform documentation.","s":"New Features","u":"/blog/page/6","p":365},{"i":373,"t":"The LAMP Platform documentation.","s":"New Features","u":"/blog/page/7","p":373},{"i":381,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/8","p":381},{"i":384,"t":"The LAMP Platform documentation.","s":"","u":"/blog/page/9","p":384},{"i":391,"t":"LAMP stands for Learn, Assess, Manage, Prevent. It is a measurement based care platform designed for both research and clinical use. The core components are the app and the dashboard.","s":"How does LAMP Platform Work?","u":"/about/intro","p":391},{"i":393,"t":"If you use the LAMP Platform in your projects or publications, please cite the latest release at the time of publication using the DOI below. (This image will automatically always display only the latest version's DOI.)","s":"Publications with LAMP","u":"/about/publications","p":393},{"i":395,"t":"BIDMC Anesthesiology and Surgery","s":"Who's using LAMP?","u":"/about/users","p":395},{"i":397,"t":"If you encounter any issues with the app, please check out our community forum//mindlamp.discourse.group/","s":"Report issues","u":"/bug","p":397},{"i":399,"t":"- [ ] Download mindLAMP app","s":"Admin Checklist","u":"/consortium/admin/checklist","p":399},{"i":401,"t":"How to add an Assess cognitive test from the Patient Profile","s":"Create an Assess Activity","u":"/consortium/admin/create_assess_activity","p":401},{"i":403,"t":"1. Navigate to the \"Activities\" tab.","s":"Create a DBT Diary Card","u":"/consortium/admin/create_dbt_diary","p":403},{"i":405,"t":"1. Log into the app and click on the \"Users\" tab.","s":"Create a New Researcher or Clinician Credential","u":"/consortium/admin/create_clinician","p":405},{"i":407,"t":"How to Create a Survey from the Patient Profile","s":"Create and Customize Surveys","u":"/consortium/admin/create_survey","p":407},{"i":409,"t":"An admin, a clinician, or a researcher can navigate to the activities page by selecting \"Studies\" on the left menu bar of the dashboard.","s":"Create a Study","u":"/consortium/admin/create_study","p":409},{"i":411,"t":"How to add a Manage activity from the Patient Profile","s":"Create a Manage Activity","u":"/consortium/admin/create_manage_activity","p":411},{"i":413,"t":"How to Create a Tip from the Patient Profile","s":"Create a Tip in Learn","u":"/consortium/admin/create_tip","p":413},{"i":415,"t":"You can add a user to an existing group. See instructions below:","s":"Create and Rename User","u":"/consortium/admin/create_user","p":415},{"i":417,"t":"→ If you'd like to access mindLAMP in a compatible desktop browser, tap here instead.","s":"Download mindLAMP","u":"/app","p":417},{"i":419,"t":"1. Log into the app and click on the \"Users\" tab.","s":"Delete a User or Share Login Link","u":"/consortium/admin/delete_user","p":419},{"i":421,"t":"→ If you'd like to access mindLAMP in a compatible desktop browser, tap here instead.","s":"Download mindLAMP","u":"/consortium/admin/download","p":421},{"i":423,"t":"Step 1: Open your phone or desktop browser and navigate to the mindLAMP app.","s":"Logging into LAMP","u":"/consortium/admin/login","p":423},{"i":425,"t":"Reset Password from the Users tab","s":"Reset a Patient's Credentials","u":"/consortium/admin/reset_user","p":425},{"i":427,"t":"1. Log into the app and click on the \"Users\" tab.","s":"Reset a Clinican or Researcher Password","u":"/consortium/admin/reset_clinician","p":427},{"i":429,"t":"Scheduling an Activity","s":"Schedule or Delete an Activity","u":"/consortium/admin/sched_delete-activity","p":429},{"i":431,"t":"To learn more about guidelines for mindLAMP use, contact Dr. John Torous at jtorous@bidmc.harvard.edu","s":"Guidelines and Principles","u":"/consortium/joining/guidelines","p":431},{"i":433,"t":"Interest Form (Part 1)","s":"Register your Interest","u":"/consortium/joining/register","p":433},{"i":435,"t":"To learn more about guidelines for mindLAMP use, contact Dr. John Torous at jtorous@bidmc.harvard.edu","s":"Requirements","u":"/consortium/joining/requirements","p":435},{"i":437,"t":"User Types","s":"Introduction","u":"/consortium/joining/intro","p":437},{"i":439,"t":"Here you will find recordings of all previous webinars in case you were unable to attend.","s":"Webinars","u":"/consortium/joining/webinars","p":439},{"i":441,"t":"→ If you'd like to access mindLAMP in a compatible desktop browser, tap here instead.","s":"Download mindLAMP","u":"/consortium/LAC/Clients/download","p":441},{"i":443,"t":"1. Log into the mindLAMP app or dashboard.","s":"Add Emotions to the DBT Diary Card","u":"/consortium/LAC/Clients/emotions","p":443},{"i":445,"t":"1. Log into the mindLAMP app or dashboard at dashboard.lamp.digital","s":"Open the DBT Diary Card","u":"/consortium/LAC/Clients/find_dbt","p":445},{"i":447,"t":"Step 1: Open your phone or desktop browser and navigate to the mindLAMP app.","s":"Logging into LAMP","u":"/consortium/LAC/Clients/login","p":447},{"i":449,"t":"1. Log into the mindLAMP app or dashboard.","s":"Add Skills to the DBT Diary Card","u":"/consortium/LAC/Clients/skills","p":449},{"i":451,"t":"1. Log into the mindLAMP app or dashboard.","s":"Add Target Behaviors to the DBT Diary Card","u":"/consortium/LAC/Clients/targets","p":451},{"i":453,"t":"1. Log into the mindLAMP app or dashboard.","s":"Add Additional Notes to the DBT Diary Card","u":"/consortium/LAC/Clients/add_note","p":453},{"i":455,"t":"1. Log in to the dashboard and navigate to the Activities tab.","s":"Create a DBT Diary Card","u":"/consortium/LAC/Clinicians/create_dbt","p":455},{"i":457,"t":"1. Log in to the dashboard and navigate to the Activities tab.","s":"Customize a DBT Diary Card","u":"/consortium/LAC/Clinicians/customize","p":457},{"i":459,"t":"1. Log in to the dashboard and navigate to the Activities tab.","s":"Customize Target Behaviors on a DBT Diary Card","u":"/consortium/LAC/Clinicians/behaviors","p":459},{"i":461,"t":"1. Log into the app and click on the \"Users\" tab.","s":"Delete a User or Share Login Link","u":"/consortium/LAC/Clinicians/delete_user","p":461},{"i":463,"t":"1. Open your phone or desktop browser and navigate to the mindLAMP app.","s":"Complete a DBT Diary Card for a Client","u":"/consortium/LAC/Clinicians/impersonate","p":463},{"i":465,"t":"Step 1: Open your phone or desktop browser and navigate to the mindLAMP app.","s":"Logging into LAMP","u":"/consortium/LAC/Clinicians/login","p":465},{"i":467,"t":"You can add a user to an existing group. See instructions below:","s":"Create and Rename a Client","u":"/consortium/LAC/Clinicians/new_user","p":467},{"i":469,"t":"Reset Password from the Users tab","s":"Reset a Client's Credentials","u":"/consortium/LAC/Clinicians/reset_user","p":469},{"i":471,"t":"Current MAPNET Specific Features and Information","s":"MAPNET","u":"/consortium/mapnet","p":471},{"i":473,"t":"1. Log into the app and click on the \"Users\" tab.","s":"Create Login Credentials for Clients","u":"/consortium/LAC/Clinicians/user_cred","p":473},{"i":475,"t":"1. Log in to the dashboard and navigate to the Activities tab.","s":"Customize Emotions on a DBT Diary Card","u":"/consortium/LAC/Clinicians/emotions","p":475},{"i":477,"t":"→ If you'd like to access mindLAMP in a compatible desktop browser, tap here instead.","s":"Download mindLAMP","u":"/consortium/patient/download","p":477},{"i":479,"t":"- [ ] Download the LAMP app","s":"Patient Checklist","u":"/consortium/patient/checklist","p":479},{"i":481,"t":"Step 1: View your Feed.","s":"Take Surveys and Complete Activities","u":"/consortium/patient/complete_activities","p":481},{"i":483,"t":"Step 1: Open your phone or desktop browser and navigate to the mindLAMP app.","s":"Logging into LAMP","u":"/consortium/patient/login","p":483},{"i":487,"t":"1. From the Activities page, select the [+Add] button.","s":"Create a DBT Diary Card for a User.","u":"/consortium/researcher/create_dbt","p":487},{"i":489,"t":"How to add an Assess cognitive test from the Patient Profile","s":"Create an Assess Activity","u":"/consortium/researcher/create_assess_activity","p":489},{"i":491,"t":"- [ ] Download the LAMP app","s":"Researcher Checklist","u":"/consortium/researcher/checklist","p":491},{"i":493,"t":"A clinician or researcher can navigate to the activities page by selecting \"Studies\" on the left menu bar of the dashboard.","s":"Create a Study","u":"/consortium/researcher/create_study","p":493},{"i":495,"t":"How to Create a Tip from the Patient Profile","s":"Create a Tip in Learn","u":"/consortium/researcher/create_tip","p":495},{"i":497,"t":"How to Create a Survey from the Patient Profile","s":"Create and Customize Surveys","u":"/consortium/researcher/create_survey","p":497},{"i":499,"t":"You can add a user to an existing group. See instructions below:","s":"Create and Rename User","u":"/consortium/researcher/create_user","p":499},{"i":501,"t":"1. Navigate to the \"Activities\" tab.","s":"Create a DBT Diary Card","u":"/consortium/researcher/DBT/create_dbt_diary","p":501},{"i":503,"t":"1. Log into the app and click on the \"Users\" tab.","s":"Delete a User or Share Login Link","u":"/consortium/researcher/delete_user","p":503},{"i":505,"t":"→ If you'd like to access mindLAMP in a compatible desktop browser, tap here instead.","s":"Download mindLAMP","u":"/consortium/researcher/download","p":505},{"i":507,"t":"Step 1: Open your phone or desktop browser and navigate to the mindLAMP app.","s":"Logging into LAMP","u":"/consortium/researcher/login","p":507},{"i":509,"t":"How to add a Manage activity from the Patient Profile","s":"Create a Manage Activity","u":"/consortium/researcher/create_manage_activity","p":509},{"i":511,"t":"Scheduling an Activity","s":"Schedule or Delete an Activity","u":"/consortium/researcher/sched_delete-activity","p":511},{"i":513,"t":"Reset Password from the Users tab","s":"Reset a Patient's Credentials","u":"/consortium/researcher/reset_user","p":513},{"i":515,"t":"Cortex is an open source analysis package. If you would like to contribute your own features, you may open a pull request.","s":"Adding Cortex Features","u":"/data_science/cortex/developing_cortex","p":515},{"i":517,"t":"computed from raw feature: cortex.raw.accelerometer","s":"Accelerometer Jerk","u":"/data_science/cortex/features/primary/acc_jerk","p":517},{"i":519,"t":"To use this feature, please use Cortex version 2022.03.11 or earlier.","s":"Sleep Periods","u":"/data_science/cortex/features/primary/deprecated_features/sleep_periods","p":519},{"i":521,"t":"computed from raw features: cortex.raw.balloonrisk, cortex.raw.catsanddogs, cortex.raw.jewelsa,","s":"Game level scores","u":"/data_science/cortex/features/primary/game_level_scores","p":521},{"i":523,"t":"Cortex cache","s":"Advanced Usage","u":"/data_science/cortex/advanced","p":523},{"i":525,"t":"computed from raw feature: cortex.raw.gps","s":"Significant Locations","u":"/data_science/cortex/features/primary/sig_locs","p":525},{"i":527,"t":"computed from raw feature: cortex.raw.gps","s":"Trips","u":"/data_science/cortex/features/primary/trips","p":527},{"i":529,"t":"computed from raw feature: cortex.raw.survey","s":"Survey scores","u":"/data_science/cortex/features/primary/survey_scores","p":529},{"i":531,"t":"computed from raw feature: cortex.raw.calls","s":"Call Degree","u":"/data_science/cortex/features/secondary/call_degree","p":531},{"i":533,"t":"computed from raw feature: cortex.raw.telephony","s":"Call Duration","u":"/data_science/cortex/features/secondary/call_duration","p":533},{"i":535,"t":"computed from raw feature: cortex.raw.calls","s":"Call Number","u":"/data_science/cortex/features/secondary/call_number","p":535},{"i":537,"t":"computed from raw feature: cortex.raw.gps or cortex.raw.accelerometer","s":"Data Quality","u":"/data_science/cortex/features/secondary/data_quality","p":537},{"i":539,"t":"To use this feature, please use Cortex version 2022.03.11 or earlier.","s":"Sleep Duration","u":"/data_science/cortex/features/secondary/deprecated_features/sleep_duration","p":539},{"i":541,"t":"computed from raw feature: cortex.raw.bluetooth","s":"Bluetooth Device Count","u":"/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count","p":541},{"i":543,"t":"computed from raw feature: cortex.raw.device_state","s":"Screen Active","u":"/data_science/cortex/features/primary/screen_active","p":543},{"i":545,"t":"To use this feature, please use Cortex version 2022.03.11 or earlier.","s":"SMS Number","u":"/data_science/cortex/features/secondary/deprecated_features/sms_number","p":545},{"i":547,"t":"computed from primary feature: cortex.primary.significant_locations","s":"Entropy","u":"/data_science/cortex/features/secondary/entropy","p":547},{"i":549,"t":"Primary features in cortex are derived from raw data and typically contain multiple bouts / periods.","s":"Primary Feature Overview","u":"/data_science/cortex/features/primary/overview","p":549},{"i":551,"t":"computed from raw feature: cortex.raw.sleep","s":"Healthkit Sleep Duration","u":"/data_science/cortex/features/secondary/healthkit_sleep_duration","p":551},{"i":553,"t":"computed from primary feature: 'cortex.primary.significant_locations'","s":"Hometime","u":"/data_science/cortex/features/secondary/hometime","p":553},{"i":555,"t":"computed from primary feature: cortex.primary.gamelevelscores","s":"Game Results","u":"/data_science/cortex/features/secondary/game_results","p":555},{"i":557,"t":"Secondary features are dervived from primary features, raw data, or a combination of both. They are designed to produce a single value per time window (i.e. time spent at home per day, etc). Thus, the data will be a list of dictionaries with keys \"timestamp\" and \"value.\"","s":"Secondary Feature Overview","u":"/data_science/cortex/features/secondary/overview","p":557},{"i":559,"t":"computed from raw feature: cortex.raw.screen_state and cortex.raw.accelerometer","s":"Inactive Duration","u":"/data_science/cortex/features/secondary/inactive_duration","p":559},{"i":561,"t":"computed from primary feature: cortex.primary.screen_active","s":"Screen Duration","u":"/data_science/cortex/features/secondary/screen_duration","p":561},{"i":563,"t":"computed from raw feature: cortex.raw.nearby_device","s":"Nearby Device Count","u":"/data_science/cortex/features/secondary/nearby_device_count","p":563},{"i":565,"t":"This feature uses the new version of the lamp.steps sensor data from April 2022. To use this feature with older data, please use Cortex version 2022.03.11 or earlier.","s":"Step Count","u":"/data_science/cortex/features/secondary/step_count","p":565},{"i":567,"t":"computed from primary feature: cortex.primary.survey_scores","s":"Survey Results","u":"/data_science/cortex/features/secondary/survey_results","p":567},{"i":569,"t":"computed from primary feature: cortex.primary.trips","s":"Trip Distance","u":"/data_science/cortex/features/secondary/trip_distance","p":569},{"i":571,"t":"computed from primary feature: cortex.primary.trips","s":"Trip Duration","u":"/data_science/cortex/features/secondary/trip_duration","p":571},{"i":573,"t":"The cortex.run() function is the easiest way to run multiple cortex features on multiple participants in a single function call.","s":"Running Cortex","u":"/data_science/cortex/running_cortex","p":573},{"i":575,"t":"Setting up Cortex","s":"Cortex Quick Start Guide","u":"/data_science/cortex/getting-started","p":575},{"i":577,"t":"utils.usefulfunctions.generateids","s":"General functions","u":"/data_science/cortex/utils/general_functions","p":577},{"i":579,"t":"utils.usefulfunctions.propagateactivity","s":"Activity functions","u":"/data_science/cortex/utils/activities","p":579},{"i":581,"t":"Warning: Directly interacting with the database can carry some risk. Please read the documentation carefully.","s":"Database functions","u":"/data_science/cortex/utils/database","p":581},{"i":583,"t":"utils.usefulfunctions.deletesensors","s":"Sensor functions","u":"/data_science/cortex/utils/sensors","p":583},{"i":585,"t":"These functions provide code for sending email, slack, and push notifications (to participants or study personnel). In order to use them you must configure either a Slack webhook (for Slack) or push API key and push gateway (for device notifcations and email).","s":"Notifications","u":"/data_science/cortex/utils/notifications","p":585},{"i":587,"t":"The module scheduling code allows researchers to specify a set of activities as a \"module\" which can then be used to easily schedule sets of activities for participants.","s":"Module scheduler","u":"/data_science/cortex/utils/module_scheduler","p":587},{"i":589,"t":"Why care about passive data?","s":"Data Quality","u":"/data_science/cortex/visualizations/data_quality","p":589},{"i":591,"t":"utils.miscfunctions.getos_version","s":"Miscellaneous","u":"/data_science/cortex/utils/miscellaneous","p":591},{"i":593,"t":"There are some basic analyses that are useful for exploring study data. The Jupyter Notebook cortex/visualizations/correlation_plots.ipynb has code to:","s":"Basic Analysis","u":"/data_science/cortex/visualizations/basic_analysis","p":593},{"i":595,"t":"At times, it may be necessary to run specific analyses on one participant - for example, to ensure continuous data quality monitoring or check the level of interaction with LAMP. The following functions are designed to run on a specific participant and return information that may be helpful either with monitoring LAMP data collection or examining cortex scores","s":"Participant-Level Visualizations","u":"/data_science/cortex/visualizations/participant_level","p":595},{"i":597,"t":"As of late September 2021, the latest versions of the LAMP platform includes a data analysis platform that allows a researcher to do some basic analyses, download data, or view pre-made graphs.","s":"Using the LAMP Data Portal","u":"/data_science/data_portal","p":597},{"i":599,"t":"①","s":"How does the LAMP Data Format Work?","u":"/data_science/data","p":599},{"i":601,"t":"The API sandbox (in the menu bar at the top of this page) allows you to test the raw HTTP REST API against a live server to see how to work with the low-level API itself.","s":"Introduction","u":"/data_science/intro","p":601},{"i":603,"t":"Overview","s":"What is Cortex?","u":"/data_science/cortex/what_is_cortex","p":603},{"i":605,"t":"All event streams in the LAMP API are catalogued by a timestamp and specific \"blueprints\" (schema) of what kind of data they hold. For example, a sensor event that occurred 20 minutes ago would carry that instant's timestamp, along with a link to what kind of sensor it was, and that sensor's measurement as a payload of data. The kinds of activities and sensors available are declared below, along with the blueprint you can expect their events' data to follow.","s":"Sensor Types","u":"/data_science/data_types/sensor_types","p":605},{"i":607,"t":"If you'd like to follow along with this tutorial but don't have a Python development environment set up, consider using Google Collab, a free service from Google Research.","s":"Preparing to Analyze Your Data in Python","u":"/data_science/python","p":607},{"i":609,"t":"All event streams in the LAMP API are catalogued by a timestamp and specific \"blueprints\" (schema) of what kind of data they hold. For example, a sensor event that occurred 20 minutes ago would carry that instant's timestamp, along with a link to what kind of sensor it was, and that sensor's measurement as a payload of data. The kinds of activities available are declared below, along with the blueprint you can expect their events' data to follow.","s":"Activity Types","u":"/data_science/data_types/activity_types","p":609},{"i":611,"t":"Although AWS is not strictly required, it is highly recommended. If you choose not to use AWS resources, members from the mindLAMP team will not be able to provide support or answer questions.","s":"Preparing Resources on AWS","u":"/deploy/aws","p":611},{"i":613,"t":" 1) \"boolean\": \"Yes\" --> 1, \"No\" --> 0 map to a dictionary: give the name of the dictionary (ex: \"map0\", and create a corresponding dictionary in the scoring_dict) Non-numeric scores are not supported at this time. \"map_to\" can be used to say that for example \"question #2\" should really be considered identical to \"quesiton #1.\" Please see the example below for an example of a scoring_dict. Data​ start: (int, units: ms) the start time of a given survey entry. end: (int, units: ms) the end time of a given survey entry. category: (str) the category of the given survey entry. question: (str) the question of the given survey entry, same as category for sum scores. score: (float) the sum of the scores for all questions in the survey entry. Note: Only questions that are in the entry will be added to the score. Please ensure that all questions you wish to be added to your score are available in the participant data. (i.e. if you are trying to sum the results of \"question 1\" and \"question 2\" but participant X only has \"question 2\" the category score for particiapnt X will be only the \"question 2\" score.) Example​ scoring_dict = { \"category_list\": [\"PHQ-9\", \"GAD-7\", \"DWAI\", \"Daily_sleep_qual\"], \"questions\": { \"Over the past week, I have felt nervous, anxious, or on edge.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have not been able to stop or control worrying.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have been worrying too much about different things.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have had trouble relaxing.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have felt so restless that it's hard to sit still.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have felt myself becoming easily annoyed or irritable.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have felt afraid as if something awful might happen.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Overall, how would you rate your sleep last night?\": {\"category\": \"Daily_sleep_qual\", \"scoring\": \"value\"}, \"How did you sleep last night?\": {\"category\": \"Daily_sleep_qual\", \"map_to\": \"Overall, how would you rate your sleep last night?\"}, \"I feel uninterested in the things I used to enjoy.\": {\"category\": \"PQ-16\", \"scoring\": \"boolean\"}, \"I often seem to live through events exactly as they happened before (déjà vu).\": {\"category\": \"PQ-16\", \"scoring\": \"boolean\"}, \"I sometimes smell or taste things that other people can’t smell or taste.\": {\"category\": \"PQ-16\", \"scoring\": \"boolean\"}, \"I trust the app to guide me towards my personal goals.\": {\"category\": \"DWAI\", \"scoring\": \"dwai_value_map\"}, \"I believe the app tasks will help me to address my problems.\": {\"category\": \"DWAI\", \"scoring\": \"dwai_value_map\"}, }, \"value_map\": { \"Not at all\": 0, \"Several days\": 1, \"More than half the days\": 2, \"Over half the days\": 2, \"Nearly every day\": 3 }, \"dwai_value_map\": { \"Strongly disagree\": 0, \"Disagree\": 1, \"Neither agree nor disagree\": 2, \"Agree\": 3, \"Strongly agree\": 4 } } cortex.primary.survey_scores.survey_scores(id=\"U1234567890\", start=0, end=cortex.now(), return_ind_ques=1, scoring_dict=scoring_dict) Output: { 'timestamp': 0, 'duration': 1627067480000, 'data': [ {'start': 1639759199227, 'end': 1639777579969, 'category': 'GAD-7', 'question': 'GAD-7', 'score': 7}, {'start': 1639759199227, 'end': 1639777579969, 'category': 'DWAI', 'question': 'DWAI', 'score': 6}, . . . {'start': 1639426388269, 'end': 1639426610663, 'category': 'Daily_sleep_qual', 'question': 'How did you sleep last night?', score': 1}, ], 'has_raw_data': 1, } Notes on the example above: The \"category_list\" may contain surveys that are not listed in the quesiton list, this will not throw an error but will also return no results. Scores are based only on the questions listed in \"questions.\" Similarly, there can be questions in \"questions\" that have categories not in \"category_list.\" These questions, if found in participant data, will not be scored. If you have multiple questions that should be considered the same, you may use \"map_to\" to point to another question. This is convinient if for example a spelling error is found and corrected during the study. Please note that answers must be the same. As shown in the \"value_map\", you may have multiple keys with the same value. Notice that the start / end time of the two returned survey scores (GAD-7 and DWAI) are the same. This is because GAD-7 questions and DWAI questions are part of the same survey in LAMP. They have been split into two seperate dictionaries here because of the way we mapped the questions to different categories (ie \"DWAI\" and \"GAD-7\") Edit this page Last updated on Nov 19, 2024 by Juan Previous Significant Locations Next Trips","s":"Survey scores","u":"/data_science/cortex/features/primary/survey_scores","h":"","p":529},{"i":532,"t":"Cortex & API Cortex Features Secondary Call Degree On this page Call Degree computed from raw feature: cortex.raw.calls Description​ Call degree is the number of different people that a participant calls. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: None) the call degree. Example​ cortex.secondary.call_degree.call_degree(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 0}, {'timestamp': 1607331600000, 'value': 2}, . . . {'timestamp': 1609232400000, 'value': 4} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Secondary Feature Overview Next Call Duration","s":"Call Degree","u":"/data_science/cortex/features/secondary/call_degree","h":"","p":531},{"i":534,"t":"Cortex & API Cortex Features Secondary Call Duration On this page Call Duration computed from raw feature: cortex.raw.telephony Description​ Call duration sums the time spent on calls. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. call_direction : (string, default: \"all\") whether to compute for incoming (\"incoming\"), outgoing (\"outgoing\"), or all (\"all\") types of calls. (deprecated) incoming: (boolean, default: True) whether to compute for incoming (True) or outgoing (False) calls. Overrides call_direction if not None. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (float, units: s) the call duration. Example​ cortex.secondary.call_duration.call_duration(call_direction=\"incoming\", id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 111}, {'timestamp': 1607331600000, 'value': 0}, . . . {'timestamp': 1609232400000, 'value': 7} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Call Degree Next Call Number","s":"Call Duration","u":"/data_science/cortex/features/secondary/call_duration","h":"","p":533},{"i":536,"t":"Cortex & API Cortex Features Secondary Call Number On this page Call Number computed from raw feature: cortex.raw.calls Description​ Call number sums the number of calls. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. call_direction : (string, default: \"all\") whether to compute for incoming (\"incoming\"), outgoing (\"outgoing\"), or all (\"all\") types of calls. (deprecated) incoming: (boolean, default: True) whether to compute for incoming (True) or outgoing (False) calls. Overrides call_direction if not None. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: None) the number of calls. Example​ cortex.secondary.call_number.call_number(call_direction=\"incoming\", id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 0}, {'timestamp': 1607331600000, 'value': 6}, . . . {'timestamp': 1609232400000, 'value': 3} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Call Duration Next Data Quality","s":"Call Number","u":"/data_science/cortex/features/secondary/call_number","h":"","p":535},{"i":538,"t":"Cortex & API Cortex Features Secondary Data Quality On this page Data Quality computed from raw feature: cortex.raw.gps or cortex.raw.accelerometer Description​ Data quality computes the percent of the time that a feature achieved a certain data quality. This feature currently supports accelerometer and gps. Note: Data quality in one of two ways 1) by pulling all raw data from 'start' to 'end' and looping over each time bin to determine if a datapoint with that timestamp in the bin exists or 2) by looping over each time bin and trying to pull a single datapoint from that time bin using the API to determine if a timestamp in that bin exists. The threshold for switching between these methods has been set to 150 bins (ie less than 150 and method #2 will be used, else method #1) to try to increase processing speed. Optional or required kwargs​ id: (str) participant id. start: (units: ms) the start time. end: (units: ms) the end time. resolution: (units: ms) the resolution over which to compute features. feature: (str, options: \"gps\" or \"accelerometer\") the feature to compute data quality. If something other than \"gps\" or \"accelerometer\" is passed None will be returned. bin_size: (float, units: ms, default: -1) the width of each bin. If set to -1 then default parameters will be used which are 1000 ms (1s) for \"accelerometer\" and 1000 * 600 ms (10min) for \"gps\". Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (float, units: None) the percent of the time that there was at least one datapoint in each bin of size bin_size. Example​ cortex.secondary.data_quality.data_quality(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000, feature=\"gps\", bin_size=10000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 1.0}, {'timestamp': 1607331600000, 'value': 0.789291823}, . . . {'timestamp': 1609232400000, 'value': 0.121212344} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Call Number Next Entropy","s":"Data Quality","u":"/data_science/cortex/features/secondary/data_quality","h":"","p":537},{"i":540,"t":"Cortex & API Cortex Features Secondary Deprecated Features Sleep Duration On this page Sleep Duration To use this feature, please use Cortex version 2022.03.11 or earlier. computed from primary feature: cortex.primary.sleep_periods computed from raw feature: cortex.raw.accelerometer Description​ Sleep duration is the sum of the sleep periods. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the sleep duration. Example​ cortex.secondary.sleep_duration.sleep_duration(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 0, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 38720178}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 12218716} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Bluetooth Device Count Next Data Quality","s":"Sleep Duration","u":"/data_science/cortex/features/secondary/deprecated_features/sleep_duration","h":"","p":539},{"i":542,"t":"Cortex & API Cortex Features Secondary Deprecated Features Bluetooth Device Count On this page Bluetooth Device Count computed from raw feature: cortex.raw.bluetooth Description​ Bluetooth device count sums the number of bluetooth device connections. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: None) the number of unique bluetooth devices. Example​ cortex.secondary.bluetooth_device_count.bluetooth_device_count(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 0}, {'timestamp': 1607331600000, 'value': 6}, . . . {'timestamp': 1609232400000, 'value': 3} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous SMS Number Next Sleep Duration","s":"Bluetooth Device Count","u":"/data_science/cortex/features/secondary/deprecated_features/bluetooth_device_count","h":"","p":541},{"i":544,"t":"Cortex & API Cortex Features Primary Screen Active On this page Screen Active computed from raw feature: cortex.raw.device_state Note: \"lamp.screen_state\" is now deprecated and has been replaced by \"lamp.device_state\". To preserve backwards compatability, Cortex will pull both \"lamp.screen_state\" and \"lamp.device_state\" events and merge them into the single raw data stream cortex.raw.device_state. Description​ Using screen_state metrics, bouts of time where the screen_state is continously in the \"on\" state are computed. The value --> representation mapping is as follows: 0 --> \"screen_on\" 1 --> \"screen_off\" 2 --> \"locked\" 3 --> \"unlocked\" Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. Data​ start: (int, units: ms) the start time of a given bout when the phone is \"on\". end: (int, units: ms) the end time of a given bout. duration: (int, units: ms) the duration of the bout (ie start - end). Example​ cortex.primary.screen_active.screen_active(id=\"U1234567890\", start=1607072400000, end=cortex.now()) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'data': [ {'start': 1607094896733, 'end': 1607100072241, 'duration': 5175508}, {'start': 1607100076065, 'end': 1607100088981, 'duration': 12916}, . . . {'start': 1607103351139, 'end': 1607108478253, 'duration': 5127114} ], 'has_raw_data': 1, } Edit this page Last updated on Nov 19, 2024 by Juan Previous Game level scores Next Significant Locations","s":"Screen Active","u":"/data_science/cortex/features/primary/screen_active","h":"","p":543},{"i":546,"t":"Cortex & API Cortex Features Secondary Deprecated Features SMS Number On this page SMS Number To use this feature, please use Cortex version 2022.03.11 or earlier. computed from raw feature: cortex.raw.sms Description​ SMS number sums the number of incoming texts. Note that many types of phones no longer provide SMS data. Optional or required kwargs​ start: number: (units: ms) the start time. end: number: (units: ms) the end time. resolution: number: (units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. Data​ timestamp: number: (units: ms) the start time of each bin of size kwargs['resolution']. value: number: (units: None) the number of texts. Example​ cortex.secondary.sms_number.sms_number(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 0}, {'timestamp': 1607331600000, 'value': 0}, . . . {'timestamp': 1609232400000, 'value': 3} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Trip Duration Next Bluetooth Device Count","s":"SMS Number","u":"/data_science/cortex/features/secondary/deprecated_features/sms_number","h":"","p":545},{"i":548,"t":"Cortex & API Cortex Features Secondary Entropy On this page Entropy computed from primary feature: cortex.primary.significant_locations computed from raw feature: cortex.raw.gps Description​ Entropy is a measure of how much a participant moves around to different locations. Higher entropy typically means that the participant's time is more evenly split between differnt locations. Assuming that p is an array holding the porportion of time at each location, entropy can be computed as follows: Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (float) the entropy. If there is no gps data, entropy will be 'None'. Example​ cortex.secondary.entropy.entropy(id=\"U1234567890\", start=1607072400000, end=1609232400000, resolution=86400000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 0.16071499652789484}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 0.8753883626144159} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Data Quality Next Game Results","s":"Entropy","u":"/data_science/cortex/features/secondary/entropy","h":"","p":547},{"i":550,"t":"Cortex & API Cortex Features Primary Primary Feature Overview On this page Primary Feature Overview Primary features in cortex are derived from raw data and typically contain multiple bouts / periods. 'has_raw_data'​ All primary features will return a has_raw_data along with the data which is whether any raw datapoints exist. Some features can return the same result if there is / is not raw data, so this flag reduces ambiguity. For example, consider screen_active (the bouts where the screen is on): cortex.primary.screen_active.screen_active(id=\"U1234567890\", start=1607072400000, end=cortex.now()) If there are screen on and off events, the data may look something like this: { 'timestamp': 1607072400000, 'duration': 5616000000, 'data': [ {'start': 1607094896733, 'end': 1607100072241, 'duration': 5175508}, {'start': 1607100076065, 'end': 1607100088981, 'duration': 12916}, . . . {'start': 1607103351139, 'end': 1607108478253, 'duration': 5127114} ], 'has_raw_data': 1, } If there is no device_state data, screen_active will return the following: { 'timestamp': 1607072400000, 'duration': 5616000000, 'data': [ ], 'has_raw_data': 0, } However, if there is device_state data, but only \"screen_off\" events (so there are no bouts where the screen is \"on\") the following will be returned: { 'timestamp': 1607072400000, 'duration': 5616000000, 'data': [ ], 'has_raw_data': 1, } Edit this page Last updated on Nov 19, 2024 by Juan Previous Advanced Usage Next Accelerometer Jerk 'has_raw_data'","s":"Primary Feature Overview","u":"/data_science/cortex/features/primary/overview","h":"","p":549},{"i":552,"t":"Cortex & API Cortex Features Secondary Healthkit Sleep Duration On this page Healthkit Sleep Duration computed from raw feature: cortex.raw.sleep Description​ Healthkit sleep duration sums the durations from the lamp.sleep sensor. The \"in_bed\", \"in_sleep\", or \"in_awake\" durations can be summed. This data only comes from watches. Please refer to section on API Feature Types for more information. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. duration_type: (str, default: \"in bed\", options: \"in_bed\", \"in_sleep\", \"in_awake\") the type of durations to sum. If an invalid duration type is passed, None will be returned. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the duration. Example​ cortex.secondary.healthkit_sleep_duration.healthkit_sleep_duration(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000, duration_type=\"in_bed\") Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': None}, {'timestamp': 1607331600000, 'value': 20000027}, . . . {'timestamp': 1609232400000, 'value': 30040029} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Game Results Next Hometime","s":"Healthkit Sleep Duration","u":"/data_science/cortex/features/secondary/healthkit_sleep_duration","h":"","p":551},{"i":554,"t":"Cortex & API Cortex Features Secondary Hometime On this page Hometime computed from primary feature: 'cortex.primary.significant_locations' computed from raw feature: 'cortex.raw.gps' Description​ The time spent at the most visited (i.e. greatest number of GPS points collected there) location (assumed to be home). For this computation, significant locations defaults to 'mode' which means that the most common locations will be based on the mode for the time period of the resolution given. Therefore, it is possible that the true \"home\" location may not be preserved over days. Note: On iOS, the accuracy of this feature may be improved by enabling \"precise location\" in permissions settings for mindLAMP. Without this toggle, this feature may be unreliable. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the time spent in the most visited location. If there is no gps data, hometime will be 'None'. Example​ cortex.secondary.hometime.hometime(id=\"U1234567890\", start=1607072400000, end=1609232400000, resolution=86400000) Output: { 'timestamp': 0, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 44145818}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 2188582} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Healthkit Sleep Duration Next Inactive Duration","s":"Hometime","u":"/data_science/cortex/features/secondary/hometime","h":"","p":553},{"i":556,"t":"Cortex & API Cortex Features Secondary Game Results On this page Game Results computed from primary feature: cortex.primary.game_level_scores computed from raw features: cortex.raw.balloon_risk, cortex.raw.cats_and_dogs, cortex.raw.jewels_a, cortex.raw.jewels_b, cortex.raw.pop_the_bubbles, cortex.raw.spatial_span Description​ Game results computes the mean score per resolution bin. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features. name_of_game: (str) the name of the game to score. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the average score. The \"score\" is based on avg_pumps for balloon_risk, avg_NO_go_perc_correct for pop_the_bubbles and avg_tap_time for cats_and_dogs, jewels_a, jewels_b, and spatial_span. Please see the documentation on the primary feature game_level_scores for more information. Example​ cortex.secondary.game_results.game_results(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000, name_of_game=\"jewels_b\") Output: { 'timestamp': 0, 'duration': 4524000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 1002.2}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 1527.82} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Entropy Next Healthkit Sleep Duration","s":"Game Results","u":"/data_science/cortex/features/secondary/game_results","h":"","p":555},{"i":558,"t":"Cortex & API Cortex Features Secondary Secondary Feature Overview Secondary Feature Overview Secondary features are dervived from primary features, raw data, or a combination of both. They are designed to produce a single value per time window (i.e. time spent at home per day, etc). Thus, the data will be a list of dictionaries with keys \"timestamp\" and \"value.\" Values for every single timestamp from start to end by resolution will be computed. Periods with no raw data will return None. Edit this page Last updated on Nov 19, 2024 by Juan Previous Sleep Periods Next Call Degree","s":"Secondary Feature Overview","u":"/data_science/cortex/features/secondary/overview","h":"","p":557},{"i":560,"t":"Cortex & API Cortex Features Secondary Inactive Duration On this page Inactive Duration computed from raw feature: cortex.raw.screen_state and cortex.raw.accelerometer Description​ Inactive duration is the sum of the inactive periods. Can be used as an estimate of sleep. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the inactive duration. Example​ cortex.secondary.inactive_duration.inactive_duration(id=\"U1234567890\", start=1607072400000, end=1609232400000, resolution=86400000) Output: { 'timestamp': 0, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 38720178}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 12218716} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Hometime Next Nearby Device Count","s":"Inactive Duration","u":"/data_science/cortex/features/secondary/inactive_duration","h":"","p":559},{"i":562,"t":"Cortex & API Cortex Features Secondary Screen Duration On this page Screen Duration computed from primary feature: cortex.primary.screen_active computed from raw feature: cortex.raw.screen_state Description​ Screen duration is the sum of the time spent with the screen \"on\". Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the screen duration. Example​ cortex.secondary.screen_duration.screen_duration(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 0, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 63720178}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 86218716} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Nearby Device Count Next Step Count","s":"Screen Duration","u":"/data_science/cortex/features/secondary/screen_duration","h":"","p":561},{"i":564,"t":"Cortex & API Cortex Features Secondary Nearby Device Count On this page Nearby Device Count computed from raw feature: cortex.raw.nearby_device Description​ Nearby device count sums the number of unique nearby bluetooth devices. Optional or required kwargs​ id: (str) the participant id. start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features (1 day = 86400000 ms). Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: None) the number of unique nearby bluetooth devices. Example​ cortex.secondary.nearby_device_count.nearby_device_count(id=\"U1753020007\", start=1646485947205, end=1647003793838, resolution=86400000) Output: { 'timestamp': 1646485947205, 'duration': 517846633, 'resolution': 86400000, 'data': [ {'timestamp': 1646485947205, 'value': 3}, {'timestamp': 1646572347205, 'value': None}, . . . {'timestamp': 1646831547205, 'value': None} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Inactive Duration Next Screen Duration","s":"Nearby Device Count","u":"/data_science/cortex/features/secondary/nearby_device_count","h":"","p":563},{"i":566,"t":"Cortex & API Cortex Features Secondary Step Count On this page Step Count This feature uses the new version of the lamp.steps sensor data from April 2022. To use this feature with older data, please use Cortex version 2022.03.11 or earlier. computed from raw feature: cortex.raw.steps Step data collected on Apple phones prior to version 2023.5.2 of mindLAMP may be cumulative, producing inaccurate results. This problem can be solved by using argument data_type='pedometer'. Description​ Step count aggregates the number of steps. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. data_type: (str; values: health, pedometer, watch; default: health) the source from which the step data is collected. health is from the Health app (Apple) or GoogleFit app (Android); pedometer is from the phone's accelerometer sensor and only works on Apple phones; and watch is from an Apple watch device. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: None) the number of steps. Example​ cortex.secondary.step_count.step_count(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 1607072400000, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 0}, {'timestamp': 1607331600000, 'value': 1027}, . . . {'timestamp': 1609232400000, 'value': 13208} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Screen Duration Next Survey Results","s":"Step Count","u":"/data_science/cortex/features/secondary/step_count","h":"","p":565},{"i":568,"t":"Cortex & API Cortex Features Secondary Survey Results On this page Survey Results computed from primary feature: cortex.primary.survey_scores computed from raw feature: cortex.raw.survey Description​ Survey results computes the mean score per resolution bin for a given category. The category should match a category in the scoring_dict. Please see the documentation on primary.survey_scores for a full description of the scoring_dict. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features. question_or_category: (str) a survey category / question to average. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the average score. Example​ scoring_dict = { \"category_list\": [\"GAD-7\"], \"questions\": { \"Over the past week, I have felt nervous, anxious, or on edge.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have not been able to stop or control worrying.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have been worrying too much about different things.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have had trouble relaxing.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have felt so restless that it's hard to sit still.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have felt myself becoming easily annoyed or irritable.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, \"Over the past week, I have felt afraid as if something awful might happen.\": {\"category\": \"GAD-7\", \"scoring\": \"value_map\"}, }, \"value_map\": { \"Not at all\": 0, \"Several days\": 1, \"More than half the days\": 2, \"Nearly every day\": 3 }, } cortex.secondary.survey_results.survey_results(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000, scoring_dict=scoring_dict, question_or_category=\"GAD-7\") Output: { 'timestamp': 0, 'duration': 4524000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 5}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 2.5} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Step Count Next Trip Distance","s":"Survey Results","u":"/data_science/cortex/features/secondary/survey_results","h":"","p":567},{"i":570,"t":"Cortex & API Cortex Features Secondary Trip Distance On this page Trip Distance computed from primary feature: cortex.primary.trips computed from raw feature: cortex.raw.gps Description​ Trip Distance is the total distance traveled on all trips in a period of time. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (float, units: km) the trip distance. Example​ cortex.secondary.trip_distance.trip_distance(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 0, 'duration': 5616000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 0.018896610358911157}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 0.0228039384631051243} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Survey Results Next Trip Duration","s":"Trip Distance","u":"/data_science/cortex/features/secondary/trip_distance","h":"","p":569},{"i":572,"t":"Cortex & API Cortex Features Secondary Trip Duration On this page Trip Duration computed from primary feature: cortex.primary.trips computed from raw feature: cortex.raw.gps Description​ Trip Duration is the total duration of all trips in a period of time. Optional or required kwargs​ start: (int, units: ms) the start time. end: (int, units: ms) the end time. resolution: (int, units: ms) the resolution over which to compute features. Data​ timestamp: (int, units: ms) the start time of each bin of size kwargs['resolution']. value: (int, units: ms) the duration of the trip. Example​ cortex.secondary.trip_duration.trip_duration(id=\"U1234567890\", start=1607072400000, end=1609232400001, resolution=86400000) Output: { 'timestamp': 0, 'duration': 4524000000, 'resolution': 86400000, 'data': [ {'timestamp': 1607072400000, 'value': 32720174}, {'timestamp': 1607331600000, 'value': None}, . . . {'timestamp': 1609232400000, 'value': 29213514} ] } Edit this page Last updated on Nov 19, 2024 by Juan Previous Trip Distance Next SMS Number","s":"Trip Duration","u":"/data_science/cortex/features/secondary/trip_duration","h":"","p":571},{"i":574,"t":"Cortex & API Cortex Running Cortex On this page Running Cortex The cortex.run() function is the easiest way to run multiple cortex features on multiple participants in a single function call. Optional or required kwargs​ id_or_set: (list of strings) a list of researchers, studies, and participants that will be expanded into a list of all participants in the set. features: (list of strings) a list of the names of raw, primary, or secondary features to run. feature_params: (dict, default=) a dictionary holding any other parameters to pass to the feature functions. start: (int, units: ms, default=None) the start time. end: (int, units: ms, default=None) the end time. Note: If start or end is set to None, the first / last timestamp with raw data will be determined. If resolution is additionally set to the number of miliseconds in a day then these timestamps will be shifted to 9am UTC. resolution: (int, units: ms, default: 1 day = 86400000 ms) the resolution over which to compute features. path_to_save: (string, default: \"\") a filepath to a directory for the features. Folders will be created for each feature and participant data will be saved in individual pickle files. run_part_and_features: (string, default: \"\") a path to a csv file with \"participant\" and \"feature\" columns to run only certain features for certain participants. cache: (boolean, default: False) whether or not to cache the raw data. print_logs: (boolean, default: False) whether to print logs. Otherwise the log level will be set to warning. Data​ If path_to_save is not set, a dictionary with keys for each feature will be created. Each feature will have a datafream with columns \"id\" for the participant id, and then any parameters in the data. Example​ cortex.run(\"dhfiej29384\", features=['screen_duration', 'data_quality'], feature_params={'screen_duration': {}, 'data_quality': {\"feature\":\"gps\", \"bin_size\":3600000}}, start=1638248400000, end=1638248400000 + 7 * MS_IN_DAY) Output: {'screen_duration': id timestamp value 0 U7869554142 2021-11-30 05:00:00 25588172.0 1 U7869554142 2021-12-01 05:00:00 15561390.0 2 U7869554142 2021-12-02 05:00:00 25896531.0 3 U7869554142 2021-12-03 05:00:00 33756622.0 4 U7869554142 2021-12-04 05:00:00 16850746.0 5 U7869554142 2021-12-05 05:00:00 19710799.0 0 U1949510612 2021-11-30 05:00:00 0.0 1 U1949510612 2021-12-01 05:00:00 184235.0 2 U1949510612 2021-12-02 05:00:00 0.0 3 U1949510612 2021-12-03 05:00:00 15452842.0 4 U1949510612 2021-12-04 05:00:00 13476068.0 5 U1949510612 2021-12-05 05:00:00 31316368.0, 'data_quality': id timestamp value 0 U7869554142 2021-11-30 05:00:00 0.791667 1 U7869554142 2021-12-01 05:00:00 0.958333 2 U7869554142 2021-12-02 05:00:00 0.916667 3 U7869554142 2021-12-03 05:00:00 1.000000 4 U7869554142 2021-12-04 05:00:00 0.958333 5 U7869554142 2021-12-05 05:00:00 0.708333 0 U1949510612 2021-11-30 05:00:00 0.041667 1 U1949510612 2021-12-01 05:00:00 0.041667 2 U1949510612 2021-12-02 05:00:00 0.000000 3 U1949510612 2021-12-03 05:00:00 0.416667 4 U1949510612 2021-12-04 05:00:00 0.750000 5 U1949510612 2021-12-05 05:00:00 1.000000} Edit this page Last updated on Nov 19, 2024 by Juan Previous What is Cortex? Next Advanced Usage","s":"Running Cortex","u":"/data_science/cortex/running_cortex","h":"","p":573},{"i":576,"t":"Cortex & API Cortex Cortex Quick Start Guide On this page Cortex Quick Start Guide Setting up Cortex​ You will need Python 3.4+ and pip installed in order to use Cortex. You may need root permissions, using sudo. Alternatively, to install locally, use pip --user. If pip is not recognized as a command, use python3 -m pip. If you meet the prerequisites, install Cortex: pip install lamp-cortex If you do not have your environment variables set up (see Advanced section below), you will need to perform the initial server credentials configuraton below: import os os.environ['LAMP_ACCESS_KEY'] = 'YOUR_EMAIL_ADDRESS' os.environ['LAMP_SECRET_KEY'] = 'YOUR_PASSWORD' os.environ['LAMP_SERVER_ADDRESS'] = 'YOUR_SERVER_ADDRESS' Source Code​ The source code can be found here: https://github.com/BIDMCDigitalPsychiatry/LAMP-cortex Example: Passive data features from Cortex​ The primary function of Cortex is to provide a set of features derived from pasive data. Data can be pulled either by calling Cortex functions directly, or by using the cortex.run() function to parse multiple participants or features simultaneously. For example, one feature of interest is screen_duration or the time spent with the phone \"on\". First, we can pull this data using the Cortex function. Let's say we want to compute the amount of time spent by participant: \"U1234567890\" from 11/15/21 (epoch time: 1636952400000) to 11/30/21 (epoch time: 1638248400000) each day (resolution = miliseconds in a day = 86400000): import cortex screen_dur = cortex.secondary.screen_duration.screen_duration(\"U1234567890\", start=1636952400000, end=1638248400000, resolution=86400000) The output would look something like this: {'timestamp': 1636952400000, 'duration': 1296000000, 'resolution': 86400000, 'data': [{'timestamp': 1636952400000, 'value': 0.0}, {'timestamp': 1637038800000, 'value': 0.0}, {'timestamp': 1637125200000, 'value': 0.0}, {'timestamp': 1637211600000, 'value': 0.0}, {'timestamp': 1637298000000, 'value': 0.0}, {'timestamp': 1637384400000, 'value': 0.0}, {'timestamp': 1637470800000, 'value': 8425464}, {'timestamp': 1637557200000, 'value': 54589034}, {'timestamp': 1637643600000, 'value': 50200716}, {'timestamp': 1637730000000, 'value': 38500923}, {'timestamp': 1637816400000, 'value': 38872835}, {'timestamp': 1637902800000, 'value': 46796405}, {'timestamp': 1637989200000, 'value': 42115755}, {'timestamp': 1638075600000, 'value': 44383154}]} The 'data' in the dictionary holds the start timestamps (of each day from 11/15/21 to 11/29/21) and the screen duration for each of these days. Second, we could have pulled this same data using the cortex.run function. Note that resolution is automatically set to a day in cortex.run. To invoke cortex.run, you must provide a specific ID or a list of IDs (only Researcher, Study, or Participant IDs are supported). Then, you specify the behavioral features to generate and extract. Once Cortex finishes running, you will be provided a dict where each key is the behavioral feature name, and the value is a dataframe. You can use this dataframe to save your output to a CSV file, for example, or continue data processing and visualization. This function call would look like this: import cortex screen_dur = cortex.run(\"U1234567890\", ['screen_duration'], start=1636952400000, end=1638248400000) And the output might look like: {'screen_duration': id timestamp value 0 U1234567890 2021-11-15 05:00:00 0.0 1 U1234567890 2021-11-16 05:00:00 0.0 2 U1234567890 2021-11-17 05:00:00 0.0 3 U1234567890 2021-11-18 05:00:00 0.0 4 U1234567890 2021-11-19 05:00:00 0.0 5 U1234567890 2021-11-20 05:00:00 0.0 6 U1234567890 2021-11-21 05:00:00 8425464.0 7 U1234567890 2021-11-22 05:00:00 54589034.0 8 U1234567890 2021-11-23 05:00:00 50200716.0 9 U1234567890 2021-11-24 05:00:00 38500923.0 10 U1234567890 2021-11-25 05:00:00 38872835.0 11 U1234567890 2021-11-26 05:00:00 46796405.0 12 U1234567890 2021-11-27 05:00:00 42115755.0 13 U1234567890 2021-11-28 05:00:00 44383154.0} The output is the same as above, except the 'data' has been transformed into a Pandas DataFrame. Additionally, the dictionary is indexed by feature -- this way you can add to the list of features processed at once. Finally, a column \"id\" has been added so that multiple participants can be processed simultaneously. We can process two participants and add \"entropy\" to our feature list. Instead of 11/15-11/29/21, let's change the timeframe to the past 7 days. If you try this with your own participant IDs, it may take a moment to run: import cortex MS_IN_A_DAY = 1000 * 60 * 60 * 24 # The miliseconds in a day features = cortex.run([\"U1234567890\", \"U0011008800\"], ['screen_duration', 'entropy'], start=cortex.now() - 7 * MS_IN_A_DAY, end=cortex.now()) Output: {'screen_duration': id timestamp value 0 U1234567890 2021-12-05 05:00:00 37035845.0 1 U1234567890 2021-12-06 05:00:00 53403478.0 2 U1234567890 2021-12-07 05:00:00 40274745.0 3 U1234567890 2021-12-08 05:00:00 46607703.0 4 U1234567890 2021-12-09 05:00:00 50506566.0 5 U1234567890 2021-12-10 05:00:00 45152245.0 0 U0011008800 2021-12-05 05:00:00 18144929.0 1 U0011008800 2021-12-06 05:00:00 49786516.0 2 U0011008800 2021-12-07 05:00:00 18542471.0 3 U0011008800 2021-12-08 05:00:00 18710925.0 4 U0011008800 2021-12-09 05:00:00 0.0 5 U0011008800 2021-12-10 05:00:00 0.0, 'entropy': id timestamp value 0 U1234567890 2021-12-05 05:00:00 -0.000000 1 U1234567890 2021-12-06 05:00:00 -0.000000 2 U1234567890 2021-12-07 05:00:00 -0.000000 3 U1234567890 2021-12-08 05:00:00 -0.000000 4 U1234567890 2021-12-09 05:00:00 0.491646 5 U1234567890 2021-12-10 05:00:00 -0.000000 0 U0011008800 2021-12-05 05:00:00 -0.000000 1 U0011008800 2021-12-06 05:00:00 -0.000000 2 U0011008800 2021-12-07 05:00:00 0.214006 3 U0011008800 2021-12-08 05:00:00 0.191434 4 U0011008800 2021-12-09 05:00:00 NaN 5 U0011008800 2021-12-10 05:00:00 NaN} Example: Retrieving survey data from Cortex​ We can also run the survey feature (which is not a behavioral feature, but rather a convenience around raw survey data) and save it to a csv using Pandas: import cortex cortex.run('YOUR_RESEARCHER_ID', ['survey'], start=0, end=cortex.now())['survey'].to_csv('~/export.csv', index=False) Yielding the following CSV output: id,timestamp,survey,item,value,type,duration,level U123456789,2020-01-16 20:57:01,RA,RA Initials,test,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire, I feel better about myself,Neither agree nor disagree,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I feel able to take chances in life,Agree Strongly,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I am able to develop positive relationships with other people ,Agree,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire, I feel part of society rather than isolated,Neither agree nor disagree,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I am able to assert myself,Disagree ,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,I feel that my life has a purpose ,Agree Strongly,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire,My experiences have changed me for the better,Agree,,0, U123456789,2020-01-16 20:56:50,SELF REPORT: Process of Recovery Questionnaire, I have been able to come to terms with things that have happened to me in the past and move on with my life,Disagree,,0, You can then load this CSV file into Microsoft Excel (or Apple Numbers on macOS). Additionally, you can add Categories to group the data by ID, survey, and the specific time that the survey was taken. Edit this page Last updated on Nov 19, 2024 by Juan Previous Preparing to Analyze Your Data in R Next What is Cortex? Setting up Cortex Source Code Example: Passive data features from Cortex Example: Retrieving survey data from Cortex","s":"Cortex Quick Start Guide","u":"/data_science/cortex/getting-started","h":"","p":575},{"i":578,"t":"Cortex & API Cortex Util Functions General functions On this page General functions utils.useful_functions.generate_ids​ Takes in a list of researcher / study / participant ids and expands it down to the participant level. Args​ id_set: (list of strings) a list of researcher, study, and participant ids. Returns​ A list of all of the participants belonging to the researchers and studies in id_set as well as the participants in id_set. Example​ utils.useful_functions.generate_ids(id_set=[\"U1234567890\", \"rdfgkd12345\"]) Output: [\"U1234567890\", \"U11111111\", \"U22222222\"] Where \"U11111111\" and \"U22222222\" are the participants of \"rdfgkd12345\" who is a researcher (or a study). utils.useful_functions.shift_time​ Take a timestamp and shift it to a certain time that same day. Args​ curr_time: (int, unit: ms) the current time (or time that should be shifted) in ms. shift: (int, default: 18 (ie 6pm)) the time to shift to in military time. Returns​ The shifted time. Example​ utils.useful_functions.shift_time(1649680020000, shift=20) Output: 1649721600000 1649680020000 is 4/11/22 at 8:27am. We set shift=20 (8pm in military time) so the output is 1649721600000 (4/11/22 at 8pm). utils.useful_functions.get_part_id_from_name​ Tries to find the participant with the attachment \"lamp.name\" set to a certain value. Args​ name: (string) the name to look for. parts: (list of strings) the list of participant IDs. Returns​ The participant ID if it was found, else -1. Example​ utils.useful_functions.get_part_id_from_name(name=\"patient 27\", parts=[\"U1234567890\", \"U2222222222\"]) Output: \"U1234567890\" Edit this page Last updated on Nov 19, 2024 by Juan Previous Participant-Level Visualizations Next Module scheduler utils.useful_functions.generate_ids utils.useful_functions.shift_time utils.useful_functions.get_part_id_from_name","s":"General functions","u":"/data_science/cortex/utils/general_functions","h":"","p":577},{"i":580,"t":"Cortex & API Cortex Util Functions Activity functions On this page Activity functions utils.useful_functions.propagate_activity​ Propagate activity takes an activity from a \"base user\" and copies the information to all other users in the list. New activities will not be created, but the information from the base user's activity will be copied into the activity with the same name in other participants if it exists. This is useful, for example, if you would like to use the dashboard to correct a typo in a survey. You can correct the typo in one user, and then use this function to propagate the change to all other active users in your study. Args​ base_user: (string) the participant id to copy the activity from. activity_name: (string) the name of the activity to copy. parts: (list of strings) the list of participant ids to copy the activity. excluded_tags: (list of strings, default: []) a list of any tags that should not be copied from the base activity to other participants. Example​ utils.useful_functions.propagate_activity(base_user=\"U1234567890\", activity_name=\"Sleep Survey\", parts=[\"U11111111\", \"U22222222\"]) utils.useful_functions.get_activity_names​ Match the ActivityEvents to the Activity name / spec. Args​ part_id: (string) the participant id. sample_length: (float, default: -1, unit=days) the number of previous days of data to include. (ex: days_ago=5 means return only data from the last 5 days) end_of_window: (float, default: current time in ms, unit=ms) the timestamp of the end of the window. Returns​ A dataframe with the ActivityEvent data with additional columns called \"name\" and \"spec\". Example​ utils.useful_functions.get_activity_names(\"U1234567890\") Output: Edit this page Last updated on Nov 19, 2024 by Juan Previous Module scheduler Next Sensor functions utils.useful_functions.propagate_activity utils.useful_functions.get_activity_names","s":"Activity functions","u":"/data_science/cortex/utils/activities","h":"","p":579},{"i":582,"t":"Cortex & API Cortex Util Functions Database functions On this page Database functions Warning: Directly interacting with the database can carry some risk. Please read the documentation carefully. These functions provide a way to directly interact with a LAMP MongoDB database and add some functionality that is not currently present in the LAMP API, such as restoring deleted activities or participants. Deleting a patient or activity through the mindLAMP dashboard does not actually erase their data from a server. Rather, it applies the 'delete' FLAG to them at a database level. As such, these functions include safeguards that should prevent unintended consequences, but directly interacting with the database can carry some risk, so please read the documentation for these functions carefully before using them. Please report any issues to community.lamp.digital. Please note: if you are using an older version of LAMP, e.g. one using CouchDB, these functions may not work. utils.db.change_parent​ Change a LAMP element's parent - e.g. move a participant from one study to another, a study from a researcher to another, or an activity from study to study. Args​ target: the target's LAMP id original_parent: the LAMP id of the original parent of the target target_parent: the LAMP id of the parent the target should be moved to db: the database this will happen in (usually 'LAMP') client_url: a valid mongodb URL w/ login info (one of this or client is required, but not both) client: a valid pymongo client Example​ import cortex MONGO_URL = \"mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]\" cortex.utils.db.change_parent('U0591253803','dynp0g0530xkahnzh0xc','ef0b54h281vfmhc0515d',client_url=MONGO_URL) Result U0591253803 updated. Moved participant from study Second Study - (dynp0g0530xkahnzh0xc) to study LAMP Testing (Internal - Luke) - (ef0b54h281vfmhc0515d) utils.db.get_survey_names​ Get the survey names and specs for all ActivityEvents for a participant. Use the database to get deleted survey ids as well. Args​ participant_id: (string) the participant id. db: (string, default: 'LAMP') the database. client_url: (string) a valid mongodb URL with login info. client: (object) a valid pymongo client Returns​ A dataframe containing the ActivityEvent data for this participant with two additional columns: \"name\" and \"spec\". Example​ YOUR_MONGO_URL = \"mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]\" utils.db.get_survey_names(\"U1234567890\", client_url=YOUR_MONGO_URL) Output: utils.db.list_deleted_activities​ Returns a list of dictionaries, each reflecting a deleted activity, with an id and name key. Args​ study_id: the study to examine db: the database this will happen in (usually 'LAMP') client_url: a valid mongodb URL w/ login info client: a valid pymongo client Example​ import cortex MONGO_URL = \"mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]\" cortex.utils.db.list_deleted_activities('dynp0g0530xkahnzh0xc',client_url=MONGO_URL) Result [{'id': 'qa0k8arrv8cx1brp724d', 'name': 'Jewels A testing'}, {'id': 'fgqyjzspc92n2nwb8d7d', 'name': 'Test Survey'}] utils.db.list_deleted_participants​ Returns a list of dictionaries, each reflecting a deleted participant, with an id key. Args​ study_id: the study to examine db: the database this will happen in (usually 'LAMP') client_url: a valid mongodb URL w/ login info client: a valid pymongo client Example​ import cortex MONGO_URL = \"mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]\" print(LAMP.Study.all_by_researcher('ffmz65mn1gtav5fq3bhq')['data']) cortex.utils.db.list_deleted_participants('ef0b54h281vfmhc0515d',client_url=MONGO_URL) Result [{'id': 'ef0b54h281vfmhc0515d', 'name': 'LAMP Testing (Internal - Luke)'}, {'id': 'dynp0g0530xkahnzh0xc', 'name': 'Second Study'}] [{'id': 'U4942710066'}] utils.db.restore_activities​ Restores activities given one or more activity ids Args​ activity_id: string or list of the LAMP IDs of the activity(s) to restore db: the database this will happen in (usually 'LAMP') client_url: a valid mongodb URL w/ login info client: a valid pymongo client restore_tags: Whether to restore any tags created on a activity Example​ import cortex MONGO_URL = \"mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]\" deleted = [x['id'] for x in cortex.utils.db.list_deleted_activities('dynp0g0530xkahnzh0xc',client_url=MONGO_URL)] cortex.utils.db.restore_activities(deleted,client_url=MONGO_URL) Result Restoring qa0k8arrv8cx1brp724d... Restoring fgqyjzspc92n2nwb8d7d... utils.db.restore_participant​ Restores participants given one or more participant ids Args​ participant_id: string or list of the LAMP IDs of the participant(s) to restore db: the database this will happen in (usually 'LAMP') client_url: a valid mongodb URL w/ login info client: a valid pymongo client restore_tags: Whether to restore any tags created on a activity Example​ import cortex MONGO_URL = \"mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]\" cortex.utils.db.restore_participant(['U4942710066'],client_url=MONGO_URL) Result Restoring U4942710066... utils.db.restore_activities_manually​ Prompts the user to enter a list of activities to undelete them Args​ study_id: the study_id to restore activities too db: the database this will happen in (usually 'LAMP') client_url: a valid mongodb URL w/ login info client: a valid pymongo client Example​ import cortex MONGO_URL = \"mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]\" print(LAMP.Study.all_by_researcher('ffmz65mn1gtav5fq3bhq')['data']) cortex.utils.db.restore_activities_manually('dynp0g0530xkahnzh0xc',client_url=MONGO_URL) Result [{'id': 'ef0b54h281vfmhc0515d', 'name': 'LAMP Testing (Internal - Luke)'}, {'id': 'dynp0g0530xkahnzh0xc', 'name': 'Second Study'}] The following activities are deleted 0:Jewels A testing:qa0k8arrv8cx1brp724d 1:Jewels B Testing:4at12eky0manz92bvhbj 2:Test Survey:fgqyjzspc92n2nwb8d7d 3:Scratch Card:8z9vcgewqt1j9vknm48d Please input, comma-seperated, the numbers of the activity you would like to restore. (e.g. 1,4) 1,3 All done. As of now: The following activities are deleted 0:Jewels A testing:qa0k8arrv8cx1brp724d 1:Test Survey:fgqyjzspc92n2nwb8d7d Edit this page Last updated on Nov 19, 2024 by Juan Previous Sensor functions Next Notifications utils.db.change_parent utils.db.get_survey_names utils.db.list_deleted_activities utils.db.list_deleted_participants utils.db.restore_activities utils.db.restore_participant utils.db.restore_activities_manually","s":"Database functions","u":"/data_science/cortex/utils/database","h":"","p":581},{"i":584,"t":"Cortex & API Cortex Util Functions Sensor functions On this page Sensor functions utils.useful_functions.delete_sensors​ Remove all sensors from a participant to stop data collection. Args​ part_id: (string) the participant id. Example​ utils.useful_functions.delete_sensors(\"U1234567890\") utils.useful_functions.add_sensor​ A wrapper for the Sensor.create function. Args​ study_id: (string) the study ID. spec: (string) the spec of the sensor (ex: \"lamp.gps\"). name: (string) what to call the sensor (shown on the dashboard). Example​ utils.useful_functions.add_sensor(\"U1234567890\", \"lamp.gps\", \"GPS sensor\") Edit this page Last updated on Nov 19, 2024 by Juan Previous Activity functions Next Database functions utils.useful_functions.delete_sensors utils.useful_functions.add_sensor","s":"Sensor functions","u":"/data_science/cortex/utils/sensors","h":"","p":583},{"i":586,"t":"Cortex & API Cortex Util Functions Notifications On this page Notifications These functions provide code for sending email, slack, and push notifications (to participants or study personnel). In order to use them you must configure either a Slack webhook (for Slack) or push API key and push gateway (for device notifcations and email). For slack, please refer to the instructions on creating a webhook here. utils.notifications.push_email​ Send an email. Support email, push API key, and push gateway must be set for sending emails. Args​ email: (str) the email to push the message to. content: (str) the content of the message. Subject and body should be split by a new line (ex: \"email subject\\nemail text\"). push_api_key: (str, default: None) the API key, will be pulled from the environment variable ('PUSH_API_KEY') if None. push_gateway: (str, default: None) the gateway, will be pulled from the environment variable ('PUSH_GATEWAY') if None. support_email: (str, default: None) the email to send from. This email will also be cc'd. debug_mode: (boolean, default: False) if set, notifications will be logged and not sent. Example​ cortex.notifications.push_email('fakeemail0@lamp.com','Hello\\nHi,

    This is a test email. Have a great day.') utils.notifications.send_push_notification​ Send a push notification to a participant. Push API key and push gateway must be set. Args​ device: (str) the device to send the message to. This information can be found using LAMP.analytics (please see the example). content: (str) the content of the message. push_api_key: (str, default: None) the API key, will be pulled from the environment variable ('PUSH_API_KEY') if None. push_gateway: (str, default: None) the gateway, will be pulled from the environment variable ('PUSH_GATEWAY') if None. expiry: (int, units: ms, default: 86400000): how long before the notification expires. debug_mode: (boolean, default: False) if set, notifications will be logged and not sent. Example​ analytics = LAMP.SensorEvent.all_by_participant(participant_id, origin=\"lamp.analytics\")['data'] all_devices = [event['data'] for event in analytics if 'device_token' in event['data']] if len(all_devices) > 0: device = f\"{'apns' if all_devices[0]['device_type'] == 'iOS' else 'gcm'}:{all_devices[0]['device_token']}\" cortex.notifications.send_push_notification(device, 'Hello, this is a test notification. Have a great day.') utils.notifications.slack​ Send a slack. Slack webhook must be set for sending slack messages. Args​ message (str): the content of the message. slack_webhook: (str, default: None) the slack webhook, will be pulled from the environment variable ('SLACK_WEBHOOK') if None. Example​ cortex.notifications.slack('This is a test slack. Have a great day.') Edit this page Last updated on Nov 19, 2024 by Juan Previous Database functions Next Miscellaneous utils.notifications.push_email utils.notifications.send_push_notification utils.notifications.slack","s":"Notifications","u":"/data_science/cortex/utils/notifications","h":"","p":585},{"i":588,"t":"Cortex & API Cortex Util Functions Module scheduler On this page Module scheduler The module scheduling code allows researchers to specify a set of activities as a \"module\" which can then be used to easily schedule sets of activities for participants. Module specification​ First, the researcher must specify what activities consitutes a module and how they should be arranged in time. Modules should be specified in a json file. Each module must include the name of the module (which should be the key in the dictionary) and a dictionary containing: \"activities\": the list of names of activities for the module which should already exist in the participants \"daily\": the list of either \"none\" or \"daily\" for if the activity should repeat daily or only occur once \"times\": the start times of each activity (relative to the start of the module, see example below) \"message\": a message to send to the participant (optional, put \"\" for no message) Here is a sample specification: { \"trial_period\": { \"activities\": [\"Trial Period Day 1\", \"Trial Period Day 2\", \"Trial Period Day 3\"], \"daily\": [\"none\", \"none\", \"none\"], \"times\": [0, 86400000, 172800000], \"message\": \"\" }, \"gratitude_journal\": { \"activities\": [\"Gratitude\", \"Gratitude Journal Day 1\", \"Gratitude Journal Day 2\", \"Gratitude Journal Day 3\", \"Gratitude Journal Day 4\", \"Gratitude Journal Day 5\", \"Gratitude Journal Day 6\"], \"daily\": [\"none\", \"none\", \"none\", \"none\", \"none\", \"none\", \"none\"], \"times\": [-60000, 60000, 86400000, 172800000, 259200000, 345600000, 432000000], \"message\": \"This week's module centers around gratitude.\" }, } In the example above, we have specified two modules, \"trial_period\" and \"gratitude_journal\". The \"trial_period\" module has 3 activities, none of which repeat. The first one will occur at the time of scheduling (for example, at 6pm on that day), the second one will happen 86400000 ms later (ie at 6pm on the second day), and the third one will happen 172800000 ms later (ie at 6pm on the third day). Notice that the first activity for \"gratitude_journal\" has a negative time. This will schedule the activity 1 minute before the scheduled start time, or at 5:59pm. Please see the source code examples for more information here: https://github.com/BIDMCDigitalPsychiatry/LAMP-cortex/tree/master/cortex/utils Setting module schedules​ Once modules have been specified, they can be scheduled in one of two ways: Configuring participant attachments to tell the system which modules should be assigned and when. Then correct_modules() is used to update participant module schedules. Use the schedule_module() function directly. Method 1: utils.module_scheduler.correct_modules​ This method requires two tags be set on participants: a phase tag and a modules tag. Here is an example phase tag: { \"status\": \"enrolled\", \"phases\": {\"enrolled\": 1649217600000, \"trial\": 1648353600000} } \"phases\" is the dictionary that holds when (in miliseconds) the participant started each phase of the study. Module scheduling is designed to only occur for particpants in the \"enrolled\" or \"trial\" phase. The module scheduler will check how long the participant has been in the given phase to determine which module should be scheduled. The second required tag is a module tag. For example: { \"trial_period\": { \"module\": \"trial_period\", \"phase\": \"trial\", \"start_end\": [0, 345600000], \"shift\": 18 }, \"gratitude_journal\": { \"module\": \"gratitude_journal\", \"phase\": \"enrolled\", \"start_end\": [0, 518400000], \"shift\": 18 }, } In this example, the participant will have the \"trial_period\" module scheduled when they are in time 0 to 345600000 ms (first 4 days) of the \"trial\" phase. In addition, the activity schedule will start at 18 (18:00), or 6pm. The \"gratitude_journal\" module will be during the \"enrolled\" phase and will last from the start of enrollment (0 ms) to the end of the first week (518400000 ms = day 6). This module will also be shifted in time to start at 6pm (18:00). With the modules specified, and phase / module tags set on the participant, correct_modules() can be called to 1) check which module the participant should be scheduled for 2) determine if this matches with the current scheduled activities and 3) make any necessary corrections to the schedules. It typically makes sense to call this function once every day or so. Args​ part_id: (string) the participant ID. PHASE_TAG: (string) the name of the phase tag. MODULE_TAG: (string) the name of the module tag. module_json: (dict, default: MODULE_JSON) the module specificaitons. Example​ utils.module_scheduler.correct_modules(\"U1234567890\", \"my_study.phases\", \"my_study.modules\", MODULE_JSON) Method 2: utils.module_scheduler.schedule_module​ This function is a helper function for correct_modules() and can be used to schedule a module for a participant. Args​ part_id: (string) the participant ID. module_name: (string) the name of the module to schedule. This must be a name in the module json. start_time: (int, units: ms) the time to use as the \"start\" / reference time for the module. This does not need to be the time of the first activity. In addition, you can use negative times to schedule some activities before the start. module_json: (dict) the specification for the modules. Example​ utils.module_scheduler.schedule_module(\"U1234567890\", \"gratitude_journal\", 1648368000000, module_json) Please see the top of this page for the example module_json. Other useful functions​ utils.module_scheduler.unschedule_other_surveys​ Uschedule all surveys for a participant (except those specified in keep_these). Args​ part_id: (string) the participant ID. keep_these: (list of strings) names of any surveys to keep the schedules for. Example​ utils.module_scheduler.unschedule_other_surveys(\"U1234567890\", keep_these=[\"Morning Daily Survey\", \"Weekly Survey\"]) utils.module_scheduler.unschedule_specific_survey​ Uschedule a specific survey. Args​ part_id: (string) the participant ID. survey_name: (string) the name of the survey to unschedule. Example​ utils.module_scheduler.unschedule_specific_survey(\"U1234567890\", \"Gratitude Journal Day 3\") Edit this page Last updated on Nov 19, 2024 by Juan Previous General functions Next Activity functions Module specification Setting module schedules Method 1: utils.module_scheduler.correct_modules Method 2: utils.module_scheduler.schedule_module Other useful functions utils.module_scheduler.unschedule_other_surveys utils.module_scheduler.unschedule_specific_survey","s":"Module scheduler","u":"/data_science/cortex/utils/module_scheduler","h":"","p":587},{"i":590,"t":"Cortex & API Cortex Visualizations Data Quality On this page Data Quality Why care about passive data?​ It is collected continuously, in the background. It can be used to help understand behaviors. Correlations with survey data can provide interesting insights. Missing data is problematic because it will affect the validity of passive features. There are multiple reasons you could have low data collection including: Permissions not set properly Low battery App has not been used in a while Remote area (for GPS) Phone not in use (OS turns off data collection) As such, it is important to monitor data to ensure that you have enough data to create good quality features. If you have participants with low data, you can follow up and try to resolve the issue. We have created visualizations that can be attached to your Data Portal on the Dashboard to provide a summary of your participant's data. These include: 1) Activity counts over the last week:​ 2) A measure of screen, GPS, and accelerometer quality over the past week:​ The graph has tool tips. If you hover over a colored block in the graph it will tell you the computed data frequency (percentage of hours with data) as well as any days where the participant had no data. 3) Average screen time, steps, and home time over the past week, as a sanity check:​ To generate these graphs, you can either call a function from Cortex, or download the source code from Github and run a bash script. To use the Cortex function, make sure that Cortex is installed. Then use the following code (substituting \"researcher_id\" with your own ID): import cortex cortex.visualizations.data_quality.data_quality(researcher_id) To run the bash script, first clone the cortex repository from source: git clone https://github.com/BIDMCDigitalPsychiatry/LAMP-cortex.git Then from inside the LAMP-cortex folder run the bash script (substituting \"researcher_id\" with your own ID): ./cortex/visualizations/run_data_quality.sh \"researcher_id\" Where are the graphs I've generated?​ Graphs are attached to the Data Portal. To Navigate to the Data Portal, go to the Dashboard and click \"Data Portal\" on the left hand side: Search for and select your researcher. Then toggle the button next to \"Analyze participant data\" to see the researcher graphs. Here, under graphs.data_quality, you should see the three graphs shown above: activity counts, passive features, and quality tags (along with any others you may have created). You can click on the buttons to view each graph. For more information, please go to the Data Portal section of the documentation. Additional functions​ We have added a couple of additional functions that can be used for more specialized situations. They are listed below and can be adapted to fit the needs of your specific study. visualizations.data_quality.make_survey_count_graph_by_name()​ Creates a graph of the counts for a specific survey / activity. Args​ participants: (list of strings) the list of participant ids and names. visualizations.data_quality.get_parts(researcher_id) can be used to generate a list. researcher_id: (string) the name of the researcher id to attach the graph to. name: (list of strings) the exact name of the survey. Example​ part_list = [{\"participant_id\": \"U11111111\", \"study_name\": \"participant1\"}, {\"participant_id\": \"U11111112\", \"study_name\": \"participant2\"}, {\"participant_id\": \"U11111113\", \"study_name\": \"participant3\"},] visualizations.data_quality.make_survey_count_graph_by_name(participants=part_list, researcher_id=\"abcdefg1234\", name=\"Morning Daily Survey\") visualizations.data_quality.make_percent_completion_graph()​ Creates a graph for the percent of required activities completed. Required activities are specified in the spec (see example below). Args​ spec: (dict) the specification dict. This includes information about which activities and how many the participant should have completed in the last X days. If a study / researcher id is given, it will be exapanded to the participant level. Please see the example below. researcher_id: (string) the name of the researcher id to attach the graph to. name: (list of strings) the name of the graph. Example​ mod_dict = [ { \"activity_name\": \"Mindfulness\", \"count\": 3, \"time_interval\": MS_IN_DAY * 5 }, { \"activity_name\": \"Morning Daily Survey\", \"count\": 7, \"time_interval\": MS_IN_DAY * 7 } ] mod_dict_2 = [ { \"activity_name\": \"Weekly Survey\", \"count\": 1, \"time_interval\": MS_IN_DAY * 7 }, { \"activity_name\": \"Morning Daily Survey\", \"count\": 7, \"time_interval\": MS_IN_DAY * 7 } ] spec = {\"U2134213402\": mod_dict, \"U3372337202\": mod_dict, \"qwifh12839\": mod_dict_2, } visualizations.data_quality.make_percent_completion_graph(spec=spec, researcher_id=\"abcdefg1234\", name=\"activity_completion\") In this example, participants \"U2134213402\" and \"U3372337202\" were required to complete 3 \"Mindfulness\" activites in the past 5 days. All participants under the \"qwifh12839\" study were required to complete 1 \"Weekly Survey\" and 7 \"Morning Daily Survey\" activities in the past week. visualizations.data_quality.clear_chart()​ Removes a chart from a researcher's Data Portal page. Args​ researcher_id: (string) the name of the researcher id where the graph is attached. name: (list of strings) the name of the graph. Example​ visualizations.data_quality.clear_chart(researcher_id=\"abcdefg1234\", name=\"data_quality_graph\") Edit this page Last updated on Nov 19, 2024 by Juan Previous Sleep Duration Next Basic Analysis Why care about passive data? 1) Activity counts over the last week: 2) A measure of screen, GPS, and accelerometer quality over the past week: 3) Average screen time, steps, and home time over the past week, as a sanity check: Where are the graphs I've generated? Additional functions visualizations.data_quality.make_survey_count_graph_by_name() visualizations.data_quality.make_percent_completion_graph() visualizations.data_quality.clear_chart()","s":"Data Quality","u":"/data_science/cortex/visualizations/data_quality","h":"","p":589},{"i":592,"t":"Cortex & API Cortex Util Functions Miscellaneous On this page Miscellaneous utils.misc_functions.get_os_version​ Attempts to parse the lamp.analytics data to get the phone OS, version and device type information. Args​ participant_id: (string) the participant id. Returns​ A dictionary comtaining \"device_type\", \"os_version\", and \"phone_type\". Each parameter will be None if it cannot be parsed or if there is no lamp.analytics data. Please note that the lamp.analytics 'user_agent' information was updated in Spring 2022. This code will not work with older data. Example​ cortex.utils.misc_functions.get_os_version(\"U1234567890\") Output: { \"device_type\": \"iOS\", \"os_version\": \"14.7.1\", \"phone_type\": \"iPhone12,1\" } Edit this page Last updated on Nov 19, 2024 by Juan Previous Notifications Next Adding Cortex Features utils.misc_functions.get_os_version","s":"Miscellaneous","u":"/data_science/cortex/utils/miscellaneous","h":"","p":591},{"i":594,"t":"Cortex & API Cortex Visualizations Basic Analysis On this page Basic Analysis There are some basic analyses that are useful for exploring study data. The Jupyter Notebook cortex/visualizations/correlation_plots.ipynb has code to: Score survey data and save it into a user specified directory. Load survey data, passive data features, and any other researcher-generated features to generate correlation plots. Compare features across groups of interest. Fit a basic logistic regression model to predict the participants group based on the features. While these functionalities are by no means comprehensive, they can provide a starting place for further exploration. Data​ Survey data​ Surveys are scored using Cortex's score_surveys() function. Results are saved by survey category by participant in individual csv files. Each csv file will have a column for the timestamp as well as columns for each question in the survey and a total score. Passive data​ Passive data should be processed prior to analysis. cortex.run() can be used to generate the file format required. In particular, secondary features should be in pickle files with a column for timestamp and a column for the value of the secondary feature. Other features​ Additional data can come in the form of \"global\" data or data that holds true across the entirety of the study (ex: number of activities, age). These features should be stored in a csv file called participantId_other_global_features.csv where each column of the dataframe is a differnet global feature. Each column that you would like to be used in analysis should be listed in the list OTHER_GLOBAL_FEATS. Other local features are \"local\" in time. These features look just like survey or passive data in that they will have a timestamp column (in ms) as well as columns for each feature. The file can be named anything, and the name of the file may or may not be in the columns. Using this filename, files will be saved in SURVEY_DIR as participantID_filename.csv. OTHER_LOCAL_FEATS should be a list of all of these file names. Then you must specify which columns in each file that should be usef in analysis. An example of how to do this in OTHER_LOCAL_SUBFEATS is shown below. Analysis​ For example, we could look at GAD-7 questions, sleep duration, and some passive data features from one of our studies. These example features are listed below. Correlations​ Using these features, we could then produce a correlation map. The * indicate signficant correlations (p < 0.05, corrected for multiple comparisons). Comparison across groups​ We could then look at whether these features differed among participants that improved over the course of the study. Significantly different groups based on a t-test (p < 0.05, corrected for multiple comparisons) are marked with *. Entropy, home time, and GPS data quality differ between the group that did and did not improve. Logistic regression model​ Finally, we fit a logistic regression model to predict which participants improved. The model achieved an AUC of 0.862 and had three non-zero coefficients: Feature Coefficient entropy 0.468 screen_duration 0.212 sleep_duration 0.223 From here, we can take a deeper look at why some features may be different across groups or investigate the relationships between correlated variables. The goal of these visualizations is to provide a starting point for further analysis. Edit this page Last updated on Nov 19, 2024 by Juan Previous Data Quality Next Participant-Level Visualizations Data Analysis","s":"Basic Analysis","u":"/data_science/cortex/visualizations/basic_analysis","h":"","p":593},{"i":596,"t":"Cortex & API Cortex Visualizations Participant-Level Visualizations On this page Participant-Level Visualizations At times, it may be necessary to run specific analyses on one participant - for example, to ensure continuous data quality monitoring or check the level of interaction with LAMP. The following functions are designed to run on a specific participant and return information that may be helpful either with monitoring LAMP data collection or examining cortex scores Passive Data Quality​ Function​ cortex.visualizations.participant.passive(id) This function produces two graphs intended to help assess data quality - a scatterplot and a heatmap, which both show on an hourly level the amount of data collected over the previous week. Data is stored in attachments to prevent unnecessary server load on subsequent runs - as such, this can be run repeatedly throughout the week to speed up individual runs. Parameters​ id_list: A string or array of strings of LAMP ids (participant, study, researcher) show_graphs: If True, graphs are displayed in the output attach_graphs: If True, graphs are attached to the participant display_graphs: If True, graphs are attached to the study and researcher for display days_ago: The number of days ago the analysis should end. If 0, analysis ends on the current timestamp sample_length: The number of days to query data for set_to_utc_midnight: If True, timestamps are adjusted to UTC midnight reporter_func: The function that should output important logging info. Use with a webhook, for example logging to slack return_dict: If true, returns a dictionary containing data output. Else returns None. reset: If true, data from previous runs will be deleted. Code Example​ researcher_id='ffmz65mn1gtav5fq3bhq' cortex.visualizations.participant.passive(researcher_id,attach_graphs=False) First Time: Found no U5946075691 data under lamp.analysis.Accel_Quality_stored Querying for U5946075691 - Accel_Quality Repeat Time: Querying for U5946075691 - GPS_Quality Previous data was found. 168 chunks were excluded. Scatterplot: Heatmap: Active Data Quality​ Function​ cortex.visualizations.participant.active(id) This function produces a graph intended to help assess participant interaction with lamp - a stacked bar chart, which shows on an daily level the number of LAMP activities collected each day. Parameters​ id_list: a string or array of strings of LAMP ids(participant, study, researcher) target_array: a list of specs, names, or ids to display. Default is all. Include '' to show all activities. exclude_array: a list of names to exclude. Default is None. exclude_groups: attempt to exclude group completions show_graphs: if True, graphs are displayed in the output attach_graphs: if True, graphs are attached to the participant display_graphs: if True, graphs are attached to the study and researcher for display graph_name: set to another string to override the default name days_ago: the number of days ago the analysis should end.If 0, analysis ends on the current timestamp sample_length: The number of days to query data for reporter_func: The function that should output important logging info.Use with a webhook, for example logging to slack return_dict: If true, returns a dictionary containing data output. Else returns None. Code Example​ cortex.visualizations.participant.active('U1978824471',attach_graphs=True,days_ago=160,sample_length=30) Cortex Tertiles​ Function​ cortex.visualizations.participant.cortex_tertiles(id) This function produces a graph intended to help assess how participant's cortex measures change day by day. Using a 'lollipop' chart, researcher can visualize whether a particpant's scores on different cortex measures are high, medium, or low, relative to a week's worth of measurements. Parameters​ target_id: Required. a string or array of LAMP user, study, or researcher ids.All user ids below one or more ids in the list (if applicable) will be run cortex_measures: Default:['acc_energy','entropy','hometime','screen_duration']. a string, list, or dict of cortex measures. If a dict, keys will be used for the array fed into run and the values will be used as labels. E.g. {'sleep_periods':'Sleep'} measure_params: Measure params to pass into cortex use_cache: If true, attempt to use cached data show_graphs:Default True. a boolean - whether to show graphs generated to the user running the function call attach_graphs:Default True. a boolean - whether to attach graphs to the participant as a tag display_graphs:Default True. a boolean - whether to display graphs tothe participant on their prevent page days_ago: Default 0. Number of days ago to end analysis. Set to 0 to end analysis today sample_length: Default 7. Timespan for analysis, in days. reporter_func: Default 'print'. A function which should take one variable,which are outputs from this function, and displays them to a user set_to_utc_midnight: Default True. Whether or not to set the utc time to true return_dict: Default False. Whether or not to return a dictionary of all cortex outputs at the end. Code Example​ cortex.visualizations.participant.cortex_tertiles(['U1978824471'],attach_graphs=True,use_cache=True) Edit this page Last updated on Nov 19, 2024 by Juan Previous Basic Analysis Next General functions Passive Data Quality Function Parameters Code Example Active Data Quality Function Parameters Code Example Cortex Tertiles Function Parameters Code Example","s":"Participant-Level Visualizations","u":"/data_science/cortex/visualizations/participant_level","h":"","p":595},{"i":598,"t":"Cortex & API Using the LAMP Data Portal On this page Using the LAMP Data Portal Overview As of late September 2021, the latest versions of the LAMP platform includes a data analysis platform that allows a researcher to do some basic analyses, download data, or view pre-made graphs. The data portal is accessible in three ways: After logging in as an administrator, click the 'Data Portal' tab on the left or bottom of your screen. After logging in as a researcher, click the 'Data Portal' tab on the left or bottom of your screen. Direct navigation to dashboard.lamp.digital/#/data_portal At this time, the data portal is not accessible using participant credentials. Data Portal Options​ There are two main ways to use the data portal - Terminal Mode and GUI Mode. To switch between these modes, click on the button marked 'Change Viewing Mode' in the upper right corner of the data portal. Choose your desired viewing mode with the toggle, then press the button marked \"Set Viewing Mode\" to set the current mode. Terminal Mode allows a user to write custom queries using the JSONata query language and directly query a LAMP database. For more information about valid JSONata queries, please see this section of the LAMP docs GUI Mode allows a user to see pre-rendered graphs or other data that have been attached to user, study or researcher as a LAMP Tag. LAMP Tags are special pieces of information attached to a user, study, or researcher. Please see the GUI Mode section below for how the LAMP Data Portal uses tags, or the LAMP API docs for information on tags and how to set and retrieve them. Both modes allow a user to download activity data (surveys, cognitive games, etc.) in the form of a csv. Downloading your data​ To download activity event data for a researcher, study, or specific participant, follow these instructions, which can be done in either viewing mode. Using the Collapse/Expand arrow buttons in the listings on the left side of the portal, navigate through your researchers (if applicable), studies, and/or users until you can see the target you want to download. If you have many users, you may find it helpful to use the search functionality by clicking the magnifying glass icon. Press the Download button to the left of the Collapse/Expand button to bring up the selection window. Change the auto-generated file name if necessary, then click the download button. At this time, it is not possible to download sensor data through the data portal due to the high volume of data required. To download sensor data for analysis, please see the appropriate section in the Cortex and API section of the LAMP docs based on your chosen programming language. Mode Specific Information Terminal Mode​ As described above, terminal mode allows you to write and execute valid JSONata queries to directly query the database, either to read data or set new parameters such as tags, which can be used by LAMP in a variety of ways. The process of using the terminal is very simple: Click in the terminal on the right side of the page and type a valid JSONata query, such as $LAMP.Study.list('RESEARCHER_ID_HERE'), which will list all studies under a specific researcher. Press the 'Run Query' button in the bottom right of the page. The result of your query will appear in the box below the terminal, which should also expand to give you a better look at the result. To write another query, simply return to step 1. GUI Mode​ GUI Mode allows you to easily see pre-existing data stored in LAMP - and is particularly useful for looking at pre-made graphs. The LAMP data portal uses the Vega visualization grammar library to generate graphs. For more info on generating graphs with Vega, please visit their docs. To analyze data for a researcher, study, or participant, navigate to the target you want to see using the Collapse/Expand arrows in the listings on the left of the data portal, then either click the right-facing arrow or, on a desktop computer, drag and drop your target into the top box on the left side of the page. If you are analyzing a researcher or study, you can choose between 'Analyze Participant Data,' which shows you data on a researcher or study-wide level across all or multiple participants, or switch the toggle off to analyze specific tag info about the researcher or study. This second option is the only one available if you are analyzing a participant. Researcher/Study-wide analysis​ To analyze shared tags, use the dropdown menu to check boxes corresponding to the tags/data you would like to see. This list is sourced from either the lamp.dashboard.researcher_tags or the lamp.dashboard.study_tags tag - if you do not see info that you expect to in this dropdown, or you see a message that there are no shared tags, try editing either lamp.dashboard.researcher_tags or lamp.dashboard.study_tags, making sure it is an array of tags you want made available. A valid example would be: [\"lamp.dashboard.experimental.gps\",\"lamp.dashboard.experimental.Exercise Habits\",\"lamp.dashboard.experimental.Self Esteem\"] You can also simply click 'Select All Shared Tags' to load all selected data. Once you have loaded your data, you can click the \"Adjust Graph Display\" button to change the size of your graphs, filter by a participant ID (or name, if they have one assigned), or change how graphs are grouped (by participant or by graph name). You can also download a PDF with the displayed graphs by clicking the Specific data analysis​ To analyze specific data, use the 'Select tag categories' dropdown menu to select a category of tag you would like to see more details about, then select a specific tag name that is listed. If you are using publicly available LAMP analysis code - e.g. from a GitHub repository or other publicly available site, graphs are likely under the 'experimental' category. Data Portal Usage Examples Below are some examples and ideas to get you started using the LAMP Data Portal. Example 1: By plotting number of gps(or other passive measure) data points received by hour, you quickly identify which (if any) of your participants may be having data collection issues. Prevent unpleasant end-of-study realizations by ensuring that all your participants are collecting the highest quality data possible. Example 2: Use Vega's easy to create and manage tooltips to fit far more data into a single graph than would be possible in a traditional paper graph - here, for example, you can both see how survey responses trend and examine specific surveys in detail. Example 3: Keep track of which activities (and how many) your participants are doing with Vega's stacked bar plots. Example 4: Use an array of charts to examine a participant's data in great detail. Here, find examples of summary graphs which show changes over time, correlation heatmaps which highlight connections between different LAMP measures (outlined in red), and the activity tracking functionality seen in example 3. Help & Updates​ The LAMP data portal is currently in alpha, as is this documentation. We are actively seeking both feedback and requests about the usability and usefulness of the data portal and this documentation. Please give us any questions, comments, or feature requests either through our community page or our public GitHub repository Edit this page Last updated on Nov 19, 2024 by Juan Previous Using Document Transformations Next Tags & Attachments Data Portal Options Downloading your data Terminal Mode GUI Mode Researcher/Study-wide analysis Specific data analysis Help & Updates","s":"Using the LAMP Data Portal","u":"/data_science/data_portal","h":"","p":597},{"i":600,"t":"Cortex & API How does the LAMP Data Format Work? On this page How does the LAMP Data Format Work? ① Activity Specification Each activity that patients/participants can interact with is defined and encapsulated in an ActivitySpec that contains the applet (written in HTML), along with a schema to describe the input and output data. ②​ Temporal Slices When a patient begins an interactive session with any activity, session-wide data about who, what, and when is recorded. Each user tap within is then automatically validated and converted into a time-indexed standardized format called a TemporalSlice. This means data processing code can be written just once and work for any activity or any user. ③​ Event Stream When the user completes the interactive session, all the TemporalSlices are packaged into chronologically ordered ActivityEvents indexed under the user's Participant object as a low-latency stream of continuously generated data. ④​ Time Series Query The researcher/data scientist can query this data at any desired temporal resolution (e.g. one millisecond, one day, one year, etc.) and filter by the type of activity (e.g. Survey, Jewels, etc.). The query can be manipulated using map/reduce document transforms and listened to notify client code directly with real-time updates. Example JSONata // Get all participants $Participant_all(\"study\").{ id, timestamp } // Get all activities $Activity_all(\"study\").{ id, ... } // Get all activity events for all participants $Participant_all(\"study\").$merge([$ActivityEvent_all(id), { \"#parent\": id }])[$exists(timestamp)] Edit this page Last updated on Nov 19, 2024 by Juan Previous Sensor Types Next Preparing to Analyze Your Data in Python ① ② ③ ④","s":"How does the LAMP Data Format Work?","u":"/data_science/data","h":"","p":599},{"i":602,"t":"Cortex & API Introduction On this page Introduction The API sandbox (in the menu bar at the top of this page) allows you to test the raw HTTP REST API against a live server to see how to work with the low-level API itself. If you're interested in working in R, Python, or JS, we recommend you try out our programming libraries instead. LAMP Protocol​ The LAMP Protocol, or Application Programming Interface (API), is the formalized inter-component language used by any app or tool connecting to the LAMP Platform. It consists of major \"surfaces\" that describe types of data, actions that may be performed on these types of data, and access and manipulation control of these data. These \"surfaces\" are designed to be compatible with the Health Level 7 (HL7) organization's Fast Healthcare Interoperability Resources (FHIR) standard resources as well as compliant with the Health Insurance Portability and Accountability Act (HIPAA). A schema (data blueprint) presented below for each type of data in relation to other types, along with a description of the properties and actions available. The use of JSON Schema at build-time codifies these schema using sets of validation rules and declared links between types and properties. Furthermore, the Spec data types use JSON Schema at run-time to constrain data from different device sensors or activity interfaces dynamically. Object Model​ ActivitySpec: (global) a representation of an interactive user interface that can be presented to Participants. SensorSpec: (global) a representation of a physical hardware sensor that can be used to passively collect data on a device owned by a Participant. Researcher: encapsulates access and control of multiple Studies. Study: encapsulates the assignment of Activities and Sensors to Participants. Activity: activates, configures, and optionally schedules, an interactive activity for the Participant to use, and optionally, receive notifications for. Sensor: activates and configures a hardware sensor on the Participant's physical device for sensor data collection. Participant: encapsulates the storage and retrieval of ActivityEvent and SensorEvent data streams. ActivityEvent: a chronologically ordered timestamp-indexed packet of data synthesized from the Participant's interaction session with an Activity, containing temporal slices representative of each tap or action within the session. Note: this object is owned both by the Participant AND the Activity, and so it is possible to query the data either cross-Activity for a specific Participant OR cross-Participant for a specific Activity. SensorEvent: a chronologically ordered timestamp-indexed packet of data synthesized by hardware sensors on a physical device being used by Participant. Note: this object is owned both by the Participant AND the Sensor, and so it is possible to query the data either cross-Sensor for a specific Participant OR cross-Participant for a specific Sensor. Each of the above data types also support the below associated data types: Type: (any of the data types above) Credential: a security credential granting authorization to read and write to this specific object and any of its children, with which all data read/write operations are appended to a global audit log. Device: a specifically identified physical hardware device, console, or browser that represents the origin of a read/write operation in the global audit log. Tag: any arbitrary key-value indexed data, either represented as a JSON object (with or without an associated JSON Schema), or as a data-url encoded string. Though the above hierarchy is described in terms of object composition, that is, in a manner similar to files recursively nested within several folders, it is important to distinguish and describe a form of object inheritance used by Spec/*/Event data types. ActivitySpec/SensorSpec: similar to apps on an App Store, the Spec object describes the schema for input (configuration) and output (data) for an interactive activity or a hardware sensor. Activity/Sensor: this object can be thought of as an 'instance' of a Spec object assigned within a Study, with a specific name, icon, schedule, customized parameters, and more. ActivityEvent/SensorEvent: represents an 'event' as part of a time series event stream recorded by the Activity or Sensor. Using the SDK​ To follow along with the sample code provided in this document, install the appropriate SDK. Currently, we officially support the following: JavaScript npm i lamp-core Python pip install LAMP-core R R -e 'install.packages(\"devtools\"); devtools::install_github(\"BIDMCDigitalPsychiatry/LAMP-r\")' Edit this page Last updated on Nov 19, 2024 by Juan Previous Training Modules Next Activity Types LAMP Protocol Object Model Using the SDK","s":"Introduction","u":"/data_science/intro","h":"","p":601},{"i":604,"t":"Cortex & API Cortex What is Cortex? On this page What is Cortex? Overview​ The Cortex data analysis toolkit is part of the LAMP Platform, enabling researchers and clinicians with a variety of backgrounds to use pre-built tools to analyze their data and build analysis pipelines. It integrates tightly across the platform to provide a unified processing pipeline to convert patient or participant data into useful features that provide valuable clinical and research insight. It offers robust support for behavioral feature extraction, interactive visualizations, and high-performance data processing through parallelization and vectorization techniques. It obviates the need for individual analyses tied to custom code for specific sensor types across various devices. It provides a companion IDE based on JupyterLab and VSCode that abstracts away login and security issues by securely injecting an authenticated connection to the server into Cortex and resulting analysis notebooks. Categories of Activity and Sensor data types alongside Cortex features synthesized from raw data streams. Availability of Wearable Sensors depends on the device type used and supported API. You may use cortex.all_features() to list all features. Why Cortex?​ The unique data structure of the LAMP platform allows all users to analyze their data without the need for a specific data science team. Cortex makes meaningful analysis easy and accessible with only a few lines of code. Robust data streams — Cortex leverages the wide variety of data collected in the LAMP platform to provide researchers, clinicians, and patients numerous features that characterize users’ moment-by-moment behaviors. These data streams are derived from data reported within the app as well as data sensed passively by user devices. Flexible — Cortex allows you to easily customize the processing of your data. For example, whether you want to view your data at hourly, daily, or weekly intervals, Cortex will automatically parse your data into the timeframe of your choice. Scalable — The LAMP platform was designed with large datasets in mind. Handling data across large studies is often a challenge. Cortex can process any amount of data, without requiring extra code. Interoperable — In Cortex, raw data from the mindLAMP app is transformed into and stored as a list of dictionaries which can easily be transformed into a Pandas DataFrame. Pandas is a popular package that provides a robust set of tools for analyzing data. For example, after processing is done and your featurized data is ready for use as a dataframe, you can perform correlational or time-series analysis with just a few lines of code. If you would like to perform analysis using another statistical package, such as R or SPSS, you can easily export the processed data in CSV/XLS format and import it in the exogenous environment. You can also run other team’s algorithms or see how your code procedures result compared to others. Cortex Engine​ The Cortex Engine breaks down data streams into three fundamental categories of \"features.\" A feature is a consolidated representation of significant behavioral measures as captured by both activities and sensors in the LAMP Platform. Features may also act as target or independent variables, for example, in the context of machine learning models. Raw Features: A \"raw\" feature is a fully virtualized Cortex-compatible abstraction of a low level data stream from the LAMP Platform (for example, survey question responses or accelerometer data). The integration of raw features allows for simplified development of analysis code both within Cortex and outside of Cortex, by avoiding the need to switch contexts between the higher-level Cortex abstractions and the lower-level underlying LAMP Protocol when writing code. For information about raw features, please see the documentation on Feature Types. Primary Features: A \"primary\" feature is a miniaturized abstraction around a raw feature that can either be used directly, or used within multiple secondary features and analyses. It acts as a reusable intermediate or bridge between these higher-level representations features and lower-level raw data streams. For example, Significant Locations is a primary feature that processes raw GPS data and groups these data points together into weighted travelled regions of significance. Secondary Features: A \"secondary\" feature is a composite (i.e. summary) clinical / behavioral representation of multiple data streams, either through raw or primary features. Secondary features are additionally windowed by time resolution (i.e. \"each day\" vs. \"each week\"). For example, Home Time is a secondary feature that buckets Significant Locations by the specified resolution and determines the amount of time an individual spent at home within that time window. Additionally, Trip Distance is a secondary feature that also relis on the Significant Locations primary feature to calculate the distance traveled by an individual per time window. It's easy to use existng features to create your own novel features, or start entirely from scratch. Cortex will automatically handle the dependency and execution graph to ensure your data streams are post-processed in the right order. Cortex also intelligently caches raw features for re-running processing code and parallelized workflows across multiple features. Features in Cortex need not handle pre-processing for variation in sensor data between Android and iOS, because the LAMP Platform harmonizes the data, accounting for various differences in functionality and recording between Apple and Android devices. For example, accelerometer measurements taken on Apple devices are measured in G's (unit of gravity) with a frame of reference experiencing -1G in the downward-facing axis, whereas measurements on Android are measured in meters per second squared (m/s^2) without a frame of reference provided. Because the platform automatically applies this harmonization step, data analysis code and Cortex feature code need not have an intrinsic understanding of the source of the data. A sample execution plan for Cortex: The clinician or researcher creates an aggregate operation. Cortex transparently interposes the correct feature layers by creating a dependency graph of data and executes each “atomic operation” (i.e. independent of external variables) in the order it computes to be most efficient. Any raw sensor data is transparently cached during execution. Examples of Algorithms​ Entropy: The variability of the time a participant spent at significant locations (i.e. clusters) determined by their GPS data. Sleep Suite​ Cortex provides daily estimated sleep duration for users, derived from sensor data. Estimates are customized to each user’s individual behavior, as Cortex finds their most common sleep window. The sleep estimation method is highly reliant on accelerometer data in particular, so users must have data from this sensor in order for Cortex to provide an accurate estimate. From this sensor data Cortex also provides estimates for time spent in active and sedentary states. Mobility Suite​ Cortex provides various features characterizing a user’s mobility in a given time window. Unlike the sleep estimates, the mobility suite can be used at any time scale, whether that is two minutes, hours, days, or months. Mobility features rely on GPS sensor data, so users must have data from this sensor in order for processing to successfully occur. Mobility features belong to one of two categories: trips and significant locations. Trips provide information on discrete movement events that a user undergoes—e.g. commuting to work or going to the grocery store. Features included in this category are trip duration, distance and count. Significant locations provide information on places that users commonly visit. The coordinates of these locations is provided as well as the amount and fragmentation of time spent at each one, such as hometime location entropy, respectively. Edit this page Last updated on Nov 19, 2024 by Juan Previous Cortex Quick Start Guide Next Running Cortex Overview Why Cortex? Cortex Engine Examples of Algorithms Sleep Suite Mobility Suite","s":"What is Cortex?","u":"/data_science/cortex/what_is_cortex","h":"","p":603},{"i":606,"t":"Cortex & API Data Types Sensor Types On this page Sensor Types All event streams in the LAMP API are catalogued by a timestamp and specific \"blueprints\" (schema) of what kind of data they hold. For example, a sensor event that occurred 20 minutes ago would carry that instant's timestamp, along with a link to what kind of sensor it was, and that sensor's measurement as a payload of data. The kinds of activities and sensors available are declared below, along with the blueprint you can expect their events' data to follow. Active sensor events are produced on a rolling basis in the background via interactions by a Participant. They are transferred to the Platform Server automatically by using the Activity API written in JavaScript. A list of existing Sensors is provided below with name and description; a live server instance must be consulted for data schema information (see GET /sensor_spec). Implementations for these hardware sensors are provided in the GitHub repository. warning All permission requests must be accepted on both iOS and Android mobile apps, regardless of whether the appropriate Sensor is activated. (i.e. Call & Text access must be approved by the user even if lamp.sms and lamp.calls is not added for the study or clinic.) Sensor Sampling Rates​ Different sensors collect and report data at different frequencies. The data sampling rate of most sensors falls into one of three broad categories: Continuous: All data is collected and uploaded with a timestamp equal to the moment it occurred. Discrete: Not all data is collected and uploaded to the server. The available data is sampled every n seconds as defined by a frequency parameter. Interval: The available data over the course of n minutes is compiled into a report describing the events in that span. There will be a single data point every n minutes. For applicable sensors, the frequency parameter is customizable. To change the frequency, see: docs.lamp.digital/start_here/updating_frequency For some sensors, the data that is returned is different for iOS versus Android phones. This is documented below. Name SensorSpec Sampling Type Requires watch / other device Analytics lamp.analytics Continuous Location lamp.gps Discrete Accelerometer lamp.accelerometer Discrete Device Motion lamp.device_motion Discrete Screen lamp.device_state Continuous Pedometer lamp.steps Interval Bluetooth & WiFi lamp.nearby_device Discrete Calls & Texts lamp.telephony Continuous Sleep lamp.sleep Continuous Y Workouts lamp.segment Continuous Y Activity Recognition lamp.activity_recognition Continuous Y Nutrition lamp.nutrition Continuous Y Blood Glucose lamp.blood_glucose Continuous Y Oxygen Saturation lamp.oxygen_saturation Continuous Y Body Temperature lamp.body_temperature Continuous Y Blood Pressure lamp.blood_pressure Continuous Y Heart Rate lamp.heart_rate Continuous Y Heart Rate Variability lamp.heartratevariability_sdnn Continuous Y Respiratory Rate lamp.respiratory_rate Continuous Y Deprecated sensors: Name SensorSpec Replaced by Requires watch / other device Device Motion lamp.gyroscope lamp.device_motion lamp.magnetometer lamp.device_motion Location lamp.distance Pedometer lamp.flights Screen lamp.screen_state lamp.device_state Calls & Texts lamp.calls lamp.telephony lamp.sms Bluetooth & WiFi lamp.bluetooth lamp.wifi lamp.nearby_device Weight lamp.weight Height lamp.height Analytics​ SensorSpec: lamp.analytics Description​ Analytics records events such as page opens, notification receipts, or login sessions. Data​ The data parameters depend on which type of event is recorded. Login analytics event: action: (string) 'login' device_token: (string) the device token of the phone device_type: (string) either 'Android' or 'iOS' user_agent: (string) app version; OS version; phone type Page open event: type: (string) the type of action (ex: 'open_page') page: (string) the page that was opened (ie 'learn', 'assess', 'manage', 'portal') activity: (string) the activity being completed, if applicable Notification event: action: (string) the type of action (ex: 'notification') device_type: (string) either 'Android' or 'iOS' content: (dict) the content and parameters of the notification actions: (list) the user actions Example​ Login analytics event: { 'data': { 'action': 'login', 'device_token': 'dCKEicz3TYyq-Zl4ScWZmc:APA91bGdIV0FSnalZ8nU_Z_ewdESw3PuYo2o6F3CZ9sAid4FNVNr7ox5GB11Hge18FGUCizO4FqytZPZMjd_gGC6bd0kaoBmdur3zn25ACuW_-X8xPCvHxQPYVzft18L6m0rQdMeB1iC', 'device_type': 'Android', 'user_agent': 'NativeCore 2022.0.27; Android 10; OnePlus; HD1905' }, 'sensor': 'lamp.analytics', 'timestamp': 1649859212042 } Page open event: { 'timestamp': 1649859218887, 'sensor': 'lamp.analytics', 'data': { 'type': 'open_page', 'page': 'learn', 'activity': None } } Notification event: { 'timestamp': 1649505601383, 'sensor': 'lamp.analytics', 'data': { 'action': 'notification', 'device_type': 'iOS', 'content': { 'expiry': 21600000, 'notificationId': '511545', 'page': '/participant/U1753020007/activity/agmgnjynhqkyqq55gegd', 'aps': { 'expiration': 10, 'badge': 0, 'push-type': 'alert', 'sound': 'default', 'content-available': 1, 'alert': 'You have a mindLAMP activity waiting for you: Morning Daily Survey..', 'mutable-content': 1, 'collapse-id': '511545' }, 'actions': [{'name': 'Open App', 'page': '/participant/U1753020007/activity/agmgnjynhqkyqq55gegd'}] }, 'user_agent': 'NativeCore 2022.2.28; iOS 15.3.1; iPhone iPhone10,4' } } Location​ SensorSpec: lamp.gps Cortex: cortex.raw.gps Description​ The location sensor records the device's current GPS coordinates. Depending on the device operating system and device battery level, the source of the data from this sensor may alternate between GPS antennae (high accuracy), cellular tower triangulation (moderate accuracy), WiFi triangulation (poor accuracy), or a combination of these. Settings​ frequency: (number, units: Hz) the required location measurement frequency; the sensor will make a best effort to match the requested frequency but no guarantees are made by the device hardware or operating system. The maximum frequency is 1 Hz. Data​ latitude: (float, units: degrees) the coordinate's latitude. longitude: (float, units: degrees) the coordinate's longitude. altitude: (float, units: meters) the coordinate's altitude, relative to sea level. accuracy: (float, units: meters) the coordinate's estimated accuracy representing the radius of a circle formed around the reported latitude/longitude pair, for which there is AT LEAST a 68% probability that the true coordinate is contained within. 0.0: no accuracy could be determined. Unsupported event properties: bearing and speed. Example​ { \"timestamp\": 1234567890, \"sensor\": \"lamp.gps\", \"data\": { \"latitude\": 80.4827, \"longitude\": 46.28344, \"altitude\": 12.12455, \"accuracy\": 48 } } Accelerometer​ SensorSpec: lamp.accelerometer Cortex: cortex.raw.accelerometer Description​ The triaxial accelerometer measures acceleration applied to the device. Each measurement is measured in Gs and is taken relative to the coordinate plane of the device, screen facing upwards. For example, a device resting face-up on a flat surface will report a measurement with the coordinate values <0, 0, 1>. For Android, the data format is different than for iOS. The device_motion information (motion, magnetic, altitude, gravity, rotation) dictionary holds only motion for lamp.accelerometer and only rotation for lamp.device_state. The data format for iOS is described below. Settings​ frequency: number: (units: Hz) the required accelerometer measurement frequency; the sensor will make a best effort to match the requested frequency but no guarantees are made by the device hardware or operating system. The current maximum frequency is 5 Hz. Data​ x: (float, units: G) the X-axis coordinate. y: (float, units: G) the Y-axis coordinate. z: (float, units: G) the Z-axis coordinate. Example​ { \"timestamp\": 1234567890, \"sensor\": \"lamp.accelerometer\", \"data\": { \"x\": 0.19378492, \"y\": 1.28473749, \"z\": -0.19384932, } } Device Motion​ SensorSpec: lamp.accelerometer.device_motion Description​ The motion sensor gathers information on the device's physical movement. It includes metrics on device rotation, experienced gravity, and magnetic field. The acceleration measure here differs from lamp.accelerometer in that this measure does not correct for gravity. For Android, the data format is different than for iOS. The device_motion information (motion, magnetic, altitude, gravity, rotation) dictionary holds only motion for lamp.accelerometer and only rotation for lamp.device_state. The data format for iOS is described below. Data​ motion: (dict) x: (float) the x-component of motion y: (float) the y-component of motion z: (float) the z-component of motion magnetic: (dict) x: (float, units: micro T) the geomagnetic field strength along the device's x-axis, where the x-axis runs from left to right, across the front screen y: (float, units: micro T) the geomagnetic field strength along the device's y-axis, where the y-axis runs vertically from the bottom to the top of the device's screen z: (float, units: micro T) the geomagnetic field strength along the device's z-axis, where the z-axis runs towards the outside of the device's screen (toward the user) altitude: (dict) x: (float) the x-component of altitude y: (float) the x-component of altitude z: (float) the y-component of altitude gravity: (dict) x: (float) the force of gravity along the device's x-axis, where the x-axis runs from left to right, across the front screen y: (float) the force of gravity along the device's y-axis, where the y-axis runs vertically from the bottom to the top of the device's screen z: (float) the force of gravity along the device's z-axis, where the z-axis runs towards the outside of the device's screen (toward the user) rotation: (dict) x: (float) the rotation vector component around the x-axis, which points tangentially along the ground, to the East: x * sin(theta/2) y: (float) the rotation vector component around the y-axis, which points tangent along the ground, to the North: y * sin(theta/2) z: (float) the rotation vector component around the z-axis, which points towards the sky, perpendicular to the ground: z * sin(theta/2) Example​ { 'sensor': 'lamp.device_motion', 'data': { 'motion': { 'x': -0.0017750263214111328, 'y': 0.004897803068161009, 'z': -0.00017660856246948242 }, 'magnetic': { 'x': 3.450927734375, 'y': 8.881887435913086, 'z': 53.096649169921875 }, 'attitude': { 'x': 2.9586798819128934, 'y': 0.1373790520467436, 'z': -0.9628289634642353 }, 'gravity': { 'x': 0.18018077313899994, 'y': -0.13694733381271362, 'z': 0.9740535616874695 }, 'rotation': { 'x': 0.001726057380437851, 'y': -0.008104033768177036, 'z': 0.004878027364611627 } }, 'timestamp': 1647386641091 } Device State​ SensorSpec: lamp.device_state Cortex: cortex.raw.screen_state Description​ The device state sensor records when the screen was turned on or off, when the device was locked or unlocked, and changes in battery level from charging or discharging the device. This sensor DOES NOT record the amount of time spent within specific apps on the device or how many notifications were received. Data​ screen_state: (int) the current device screen / lock state. 0: screen_on; the screen was turned on, either by the user or by a notification. 1: screen_off; the screen was turned off, either by the user or by screen timeout. 2: device_locked; the device was locked, either by the user or by device timeout. 3: device_unlocked; the device was unlocked by the user. 4: battery_charging; the device was plugged in to charge by the user. 5: battery_unplugged; the device was unplugged from the charger by the user. battery_level: (float, units: percentage) the current battery level of the device. Example​ { 'sensor': 'lamp.device_state', 'data': { 'value': 1, 'representation': 'screen_off', 'battery_level': 0.07000000029802322 }, 'timestamp': 1649465295573 } Steps​ SensorSpec: lamp.steps Cortex: cortex.raw.steps Description​ The step sensor records the number of steps since the last reading. On iOS, the behavior may be that each event fetches the current running count of steps during the calendar day specified by timestamp (in this case, source will be null). If fetching HealthKit data (i.e. source is NOT null), the events will instead capture number of steps since the last recorded event (which may be the desired behavior). Data​ source: (string) the source of the data. If the source is not available, it will be set to null. type: (string) the type of data (ex: \"step_count\", \"speed\", \"distance\"). unit: (string) the units of the data. value: (float) the value of the data. Example​ { \"data\": { \"source\": \"com.google.android.gms\", \"type\": \"step_count\", \"unit\": \"count\", \"value\": 13 }, \"sensor\": \"lamp.steps\", \"timestamp\": 1649842803515 } Nearby device​ SensorSpec: lamp.nearby_device Description​ The nearby device sensor records bluetooth and wifi connections. Data​ type: (string) Type of connection (WiFi or bluetooth) name: (string) Name of the device address: (string) Address of connected device strength: (int, units: DB) WiFI or bluetooth signal strength. RSSI is a term used to measure the relative quality of a received signal to a client device, but has no absolute value. […] Cisco, for example, uses a 0-100 scale, while Atheros uses 0-60. It’s all up to the manufacturer (which is why RSSI is a relative index), but you can infer that the higher the RSSI value is, the better the signal is. […] There’s a lot of math we could get into, but basically, the closer to 0 dBm, the better the signal is. -- Source Signal Strength TL;DR -30 dBm Amazing -67 dBm Very Good -70 dBm Okay -80 dBm Not Good -90 dBm Unusable Example​ { 'data': { 'strength': '-95', 'type': 'bluetooth', 'name': 'device1', 'address': '3FC6C779-D79C-E00A-B711-5B2C8CA3D313'}, 'sensor': 'lamp.nearby_device', 'timestamp': 1649866397374 }, { 'data': { 'strength': 0, 'type': 'wifi', 'name': 'CNW-WLAN', 'address': 'e2:cc:ac:be:67:4d'}, 'sensor': 'lamp.nearby_device', 'timestamp': 1659729455051}, } Telephony​ SensorSpec: lamp.telephony Description​ The telephony records phone call information. Data​ duration: (float, units: s) the duration of the call type: (string) \"incoming\" or \"outgoing\" Example​ { 'data': { 'type': 'incoming' 'duration': 24, 'trace': '22F222FF-F2F2-4000-92F3-293049DC4FEC', }, 'sensor': 'lamp.telephony', 'timestamp': 1649864919743 } Sleep​ SensorSpec: lamp.sleep Cortex: cortex.raw.sleep Description​ The sleep sensor reports sleep data stored on the phone, generally sourced from smartwatches such as an Apple Watch. If you plan on capturing data via an Android device, you may need to test to ensure the associated watch is high enough quality to regularly collect good data. Data​ value: (int) 0, 1, or 2, if the user is in bed, asleep, or awake, respectively source: (string) the source of data, e.g. com.apple.health duration: (int, unit: ms) the time in ms the specific activity (e.g. sleep) lasted representation: (string) one of in_bed, in_sleep, or in_awake, reflecting the state of the user at the time of measurement Example​ { 'sensor': 'lamp.sleep', 'data': { 'value': 0, 'source': 'com.apple.health.CACD64E0-EE17-4430-9B0B-5255F09075DE', 'representation': 'in_bed', 'duration': 12523000 } 'timestamp': 1636639670000 } Sensors requiring extra devices​ There are several sensors that require external hardware to collect data. These sensors should be fully tested before usage. This includes: lamp.blood_pressure lamp.respiratory_rate lamp.heart_rate lamp.segment (workout segmentation) lamp.activity_recognition lamp.nutrition lamp.blood_glucose lamp.body_temperature lamp.heartratevariability_sdnn Data from these sensors will be of the form: value (float): the value of the sensor. unit (string): the units of the data. Deprecated sensors​ Bluetooth​ SensorSpec: lamp.bluetooth Description​ The bluetooth sensor logs information about the device's Bluetooth sensor and about surrounding Bluetooth devices that are enabled and/or visible. The device scan for surrounding Bluetooth devices at a set frequency (default is 60 seconds). If multiple devices are detected in a single scan, they are all assigned the same timestamp. Data​ bt_address: (string) address of Bluetooth event. bt_rssi: (int, units: DB) WiFI signal strength. RSSI is a term used to measure the relative quality of a received signal to a client device, but has no absolute value. […] Cisco, for example, uses a 0-100 scale, while Atheros uses 0-60. It’s all up to the manufacturer (which is why RSSI is a relative index), but you can infer that the higher the RSSI value is, the better the signal is. […] There’s a lot of math we could get into, but basically, the closer to 0 dBm, the better the signal is. -- Source Signal Strength TL;DR -30 dBm Amazing -67 dBm Very Good -70 dBm Okay -80 dBm Not Good -90 dBm Unusable Example​ { 'timestamp': 1616172858929, 'sensor': 'lamp.bluetooth', 'data': { 'bt_rssi': -91, 'bt_address': 'CCF087D3-A0FC-0FDF-D7F9-1285211653FB' } } Calls​ SensorSpec: lamp.calls Description​ The calls sensor measures information on phone calls made and received by the user. Each event is a single phone call, with information on its type (incoming, outgoing, missed, etc), duration, and trace (the other device which the user connected with during the call). Call type options differ between Android and iOS devices. This sensor has been replaced by lamp.telephony. Data​ call_trace: (string) the SHA-1-encrypted source/target of the call. A device will have a consistent trace. call_type: (int): integer label for the call type 1: incoming; the call was received by the user 2: outgoing; the call was made by the user call_duration: (int, units: seconds) the length of the call session. Example​ { 'timestamp': 1609711564846, 'sensor': 'lamp.calls', 'data': { 'call_trace': '4DE07C9D-6496-41B5-B9F9-DCFDA746FE49', 'call_type': 2, 'call_duration': 23 } } Distance​ SensorSpec: lamp.distance Data​ value: (float) the distance. Example​ { 'timestamp': 1609791149998, 'sensor': 'lamp.distance', 'data': { 'value': 6685.931218739017 } } Gyroscope​ SensorSpec: lamp.gyroscope Description​ The gyroscope sensors measures the rate of rotation around each of a device's x, y and z axes. Rotation values are in radians/second. Positive values indicate counter-clockwise rotation; negative values indicate clockwise rotation. These are raw values—i.e. they do not correct for nosie or drift. This sensor has been replaced by lamp.device_motion. Data​ x: (float, units: rad/s) the rotational velocity around the x-axis. The x-axis goes from left to right, across the device's screen face y: (float, units: rad/s) the rotational velocity around the y-axis. The y-axis is vertical and points up z: (float, units: rad/s) the rotational velocity around the z-axis. The z-axis is horizontal and points out from the front screen (towards the user looking at the screen) Example​ { 'timestamp': 1609796944931, 'sensor': 'lamp.gyroscope', 'data': { 'x': -0.018976621329784393, 'y': -0.0030131004750728616, 'z': -0.01834332011640072 } } SMS​ SensorSpec: lamp.sms Description​ The sms sensor measures information on text messages sent and received by the user. Each event is a single message, with information on its type (incoming, outgoing) and trace (the other device involved in the messaging exchange). Data​ trace (string): the SHA-1-encrypted source/target of the text message. A device will have a consistent trace. type: (int): integer label for the message type 1: received; the message was received by the user 2: sent; the message was sent by the user Screen​ SensorSpec: lamp.screen_state Description​ The screen state sensor records when the screen was turned on or off, when the device was locked or unlocked, and changes in battery level from charging or discharging the device. This sensor DOES NOT record the amount of time spent within specific apps on the device or how many notifications were received. lamp.screen_state has been replaced with lamp.device_state Data​ screen_state: (int) the current device screen / lock state. 0: screen_on; the screen was turned on, either by the user or by a notification. 1: screen_off; the screen was turned off, either by the user or by screen timeout. 2: device_locked; the device was locked, either by the user or by device timeout. 3: device_unlocked; the device was unlocked by the user. 4: battery_charging; the device was plugged in to charge by the user. 5: battery_unplugged; the device was unplugged from the charger by the user. battery_level: (float, units: percentage) the current battery level of the device. Example​ { 'sensor': 'lamp.screen_state', 'data': { 'value': 1, 'representation': 'screen_off', 'battery_level': 0.07000000029802322 }, 'timestamp': 1649465295573 } Weight​ SensorSpec: lamp.weight Height​ SensorSpec: lamp.height WiFi​ SensorSpec: lamp.wifi Cortex: cortex.raw.wifi Description​ The wifi sensor provides information about the devices to which the user's device connects via wifi. The new version of this sensor is lamp.nearby_device. Data​ bssid: (string) BSSID of WiFi event ssid: (string) SSID of WiFi event Example​ { 'timestamp': 1609796928526, 'sensor': 'lamp.wifi', 'data': { 'bssid': 'a4:2b:b2:d3:d:52', 'ssid': 'RB_Tiger' } } Flights​ SensorSpec: lamp.flights Description​ Records stairs of flights climbed. Magnetometer​ SensorSpec: lamp.magnetometer Description​ Records triaxial magnetic field changes. This sensor has been replaced by lamp.device_motion. Data​ x: (float, units: micro T) the geomagnetic field strength along the device's x-axis, where the x-axis runs from left to right, across the front screen y: (float, units: micro T) the geomagnetic field strength along the device's y-axis, where the y-axis runs vertically from the bottom to the top of the device's screen z: (float, units: micro T) the geomagnetic field strength along the device's z-axis, where the z-axis runs towards the outside of the device's screen (toward the user) Example​ { 'timestamp': 1609796944931, 'sensor': 'lamp.magnetometer', 'data': { 'x': -25.963943481445312, 'y': -2.191162109375, 'z': -403.3388977050781 } } Edit this page Last updated on Nov 19, 2024 by Juan Previous Activity Types Next How does the LAMP Data Format Work? Sensor Sampling Rates Analytics Location Accelerometer Device Motion Device State Steps Nearby device Telephony Sleep Sensors requiring extra devices Deprecated sensors Bluetooth Calls Distance Gyroscope SMS Screen Weight Height WiFi Flights Magnetometer","s":"Sensor Types","u":"/data_science/data_types/sensor_types","h":"","p":605},{"i":608,"t":"Cortex & API Preparing to Analyze Your Data in Python On this page Preparing to Analyze Your Data in Python If you'd like to follow along with this tutorial but don't have a Python development environment set up, consider using Google Collab, a free service from Google Research. Installation and Setup First install the package. pip install LAMP-core Then, import the library and connect to the server. import LAMP LAMP.connect('my_email@address.com', 'my_password', 'api.lamp.digital') Usage Protocol methods​ Methods native to the LAMP API can now be called to pull data from the platform. For example, we can find all of the participants belonging to a Researcher: TEST_RESEARCHER = 'UmVzZWFyY2hlcjoxNjM~' [LAMP.Participant.all_by_study(study['id'])['data'] for study in LAMP.Study.all_by_researcher(TEST_RESEARCHER)['data']] # OUTPUT #{'data': [{'id': 'U34260565', # 'language': 'en', # 'theme': '#359FFE', # 'emergency_contact': None, # 'helpline': None}, # {'id': 'U33327158', # 'language': 'en', # 'theme': '#359FFE', # 'emergency_contact': None, # 'helpline': None}]} The code below will make CSV files of all the 'lamp.gps.contextual' sensor events for all participants under a given researcher id: import LAMP import pandas as pd LAMP.connect(\"MY_EMAIL_ADDRESS_HERE\", \"MY_PASSWORD_HERE\") for participant in LAMP.Participant.all_by_researcher(\"me\")['data']: data = [] events = LAMP.SensorEvent.all_by_participant(participant['id'], origin='lamp.gps.contextual')['data'] for event in events: data.append({ 'timestamp': event['timestamp'], 'UTC time': \"\", 'latitude': event['data']['latitude'], 'longitude': event['data']['longitude'], 'altitude': 1.0, 'accuracy': 1.0 }) # Don't make CSV files for participants without any `lamp.gps.contextual` events. if len(data) > 0: pd.DataFrame.from_dict(data, orient='columns').to_csv(f\"{participant['id']}.csv\", index=False) Querying sensor data​ Query sensor data with \"all_by_participant\" Specify a sensor with \"origin\". If no origin is passed, it will try to query all sensors Note that due to device or user specification, some spensors may not have data # Full sensor specs at https://docs.lamp.digital/Data-Types-99b045852c7b406f87c124b927fe95fa # Please note that no GPS data has been included with these dummy profiles participant_1 = \"U5704591513\" lamp_sensors = [\"lamp.accelerometer\", \"lamp.accelerometer.motion\", \"lamp.analytics\", \"lamp.blood_pressure\", \"lamp.bluetooth\", \"lamp.calls\", \"lamp.distance\", \"lamp.flights\", \"lamp.gps\", \"lamp.gps.contextual\", \"lamp.gyroscope\", \"lamp.heart_rate\", \"lamp.height\", \"lamp.magnetometer\", \"lamp.respiratory_rate\" \"lamp.screen_state\",\"lamp.segment\", \"lamp.sleep\", \"lamp.steps\", \"lamp.weight\", \"lamp.wifi\"] LAMP.SensorEvent.all_by_participant(participant_1, origin=\"lamp.bluetooth\")['data'][:5]#, origin=\"lamp.calls\") [{'timestamp': 1578863459719, 'sensor': 'lamp.bluetooth', 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==', 'RSSI': -71}}, {'timestamp': 1578863459533, 'sensor': 'lamp.bluetooth', 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==', 'RSSI': -74}}, {'timestamp': 1578863459196, 'sensor': 'lamp.bluetooth', 'data': {'hashed MAC': '1EKJ5ZTXj_h85oA6mP8kGq84oWSB5uaRJRlaepCb4vhPTPifquqjWJ237bsh7FEtbNrH9f45h2HSMdTffTmb_Q==', 'RSSI': -60}}, {'timestamp': 1578863459167, 'sensor': 'lamp.bluetooth', 'data': {'hashed MAC': 'YyTeKHTPetzGdC0j2EPJ9-VJ9FxafDpHd34MA41BQDKSt1Q4B7vtuFJZpN7_JTOKnDycjRcA3ik8pYwcrfFGlQ==', 'RSSI': -98}}, {'timestamp': 1578863458989, 'sensor': 'lamp.bluetooth', 'data': {'hashed MAC': 'lYcGRvQlyI9Gq8Yqu1wDX8mOQJDBzIMnnGS9UsVxsrsmKWb1nFOY0tLLAE8VTzJ83GeJaBhmnhpL8weRv7A96Q==', 'RSSI': -97}}] Example: Query accelerometer data​ Accelerometer data points are SensorEvents with the origin \"lamp.accelerometer\". See LAMP-py documentation at https://github.com/BIDMCDigitalPsychiatry/LAMP-py for further API details. Query responses are limtied to 1000 entries. In the event that there are more than 1000 events for a given sensor, the most recent 1000 events are returned. To access more data—or to query during a specific time range—you must use the \"_to\" and \"from\" parameters # '_from' and 'to' are UNIX timestamps participant_accel_tr = LAMP.SensorEvent.all_by_participant(participant_1, origin=\"lamp.accelerometer\", _from=1577735460618, to=1577735460737) participant_accel_tr['data'] Query activity event data​ Surveys are ActivityEvents, with each survey type defined as an Activity 'duration' is the survey completion time, in ms 'activity' is the Activity id 'temporal_slices' contains responses for each survey question LAMP.ActivityEvent.all_by_participant(participant_1)['data'][0] # {'timestamp': 1600557560000, # 'duration': 15000, # 'activity': '16fnz109gs4sehyfc84n', # 'static_data': {}, # 'temporal_slices': [{'item': 'How did you feel this week?', # 'value': 'Okay', # 'type': 'valid', # 'duration': 5000, # 'level': None}, # {'item': 'Have you been admitted to the hospital for psychiatric reasons in the past week?', # 'value': 'No', # 'type': 'valid', # 'duration': 7000, # 'level': None}, # {'item': 'Use this space to write down your thoughts and feelings about the week. ', # 'value': 'it was okay', # 'type': 'valid', # 'duration': 3000, # 'level': None}]} Details of the 'activity can be be viewed the following method LAMP.Activity.view('16fnz109gs4sehyfc84n') Edit this page Last updated on Nov 19, 2024 by Juan Previous How does the LAMP Data Format Work? Next Preparing to Analyze Your Data in R Protocol methods Querying sensor data Example: Query accelerometer data Query activity event data","s":"Preparing to Analyze Your Data in Python","u":"/data_science/python","h":"","p":607},{"i":610,"t":"Cortex & API Data Types Activity Types On this page Activity Types All event streams in the LAMP API are catalogued by a timestamp and specific \"blueprints\" (schema) of what kind of data they hold. For example, a sensor event that occurred 20 minutes ago would carry that instant's timestamp, along with a link to what kind of sensor it was, and that sensor's measurement as a payload of data. The kinds of activities available are declared below, along with the blueprint you can expect their events' data to follow. In the case of activities (active data) completed by the participant or patient, the activity declares two types of blueprints: static data, or data that relates to the overall session, and temporal slices, data that provides millisecond precision and carries information about each action the participant took. Activities that can be customized will also have settings blueprints, but these won't actually appear in the event data (and are omitted from the fields listed below). Survey​ ActivitySpec: lamp.survey Description​ Customizable surveys. Available question types currently include: Text: A free-entry text box Boolean: A choice between \"True\" and \"False\" List: A radio button style list where a maximum of one option can be chosen Multi-Select: A checkbox style list where multiple options can be chosen Slider: A draggable slider to select one option from a numerical range Short Answer: A smaller, free entry text box Rating: A question which asks the participant to rate something on a numerical scale Time: A interactive dropdown which allows the user to select a time. Choose between AM/PM and military options Settings​ name: A string title to display to the user settings: An array of objects, one for each question text : A string to display to the user type : The question type. One of text,boolean,list,multiselect,slider,short,rating,time required: True or False. Whether the question must be completed to advance. List options : An array of strings each corresponding to one option Multi-Select options : An array of strings each corresponding to one option Slider options : An array of numbers each corresponding to one option Rating options : An array of numbers each corresponding to one option Time options : An object with one key-value pair: timepattern: One of standard or ampm corresponding to the time selection method Example {'category': ['assess'], 'id': '5ha5qf49shjzmasrcrah', 'name': 'Rating Test', 'schedule': [], 'settings': [{'required': True, 'text': 'Text Question', 'type': 'text'}, {'required': True, 'text': 'Boolean', 'type': 'boolean'}, {'options': ['Option 1', 'Option 2'], 'required': True, 'text': 'List', 'type': 'list'}, {'options': ['Option 1', 'Option 2'], 'required': True, 'text': 'Multi-Select', 'type': 'multiselect'}, {'options': [0, 1], 'required': True, 'text': 'Slider', 'type': 'slider'}, {'required': True, 'text': 'Short Answer', 'type': 'short'}, {'options': [0, 1], 'required': True, 'text': 'Rating', 'type': 'rating'}, {'options': {'timePattern': 'standard'}, 'required': True, 'text': 'Time', 'type': 'time'}], 'spec': 'lamp.survey'} Data​ static_data: Unused. temporal_slices: item: (string) The question text. value: (string) The selected question option text. type: Unused. duration: The time taken to answer a question in the survey. level: Unused. Example​ {'timestamp': 1634047106612, 'activity': 'e2wxcekbb0typzdtz0pb', 'static_data': {}, 'temporal_slices': [{'item': 'Question 1', 'value': '1', 'type': None, 'level': None, 'duration': 2500}, {'item': 'Question 2', 'value': '1', 'type': None, 'level': None, 'duration': 1235}], 'duration': 0} Balloon Risk​ ActivitySpec: lamp.balloon_risk Description​ The Balloon Risk test is a computerized assessment of risk-taking behavior. Participants click a button to continuously blow up a balloon until they either chose to \"save their points\" and move on to the next balloon or the balloon \"pops\" after being inflated too many times. Settings​ balloon_count: Number of balloons the participant interacts with breakpoint_mean: The average value the balloon will pop at breakpoint_std: The standard deviation of the value the balloon will pop at. Data​ static_data: points: The associated point value with the completed session. temporal_slices: item: Pump number. value: 0 (exploded); 1 (unexploded). type: False (exploded); True (unexploded). duration: Time elapsed in s since last event. level: Balloon number. Example​ {'balloon_count': 15, 'breakpoint_mean': 64.5, 'breakpoint_std': 37, 'static_data': {'points': 55}, 'temporal_slices': [{'duration': 1821, 'item': 1, 'level': 1, 'type': True, 'value': 1}, {'duration': 876, 'item': 2, 'level': 1, 'type': True, 'value': 1}, {'duration': 425, 'item': 3, 'level': 1, 'type': True, 'value': 1}, {'duration': 167, 'item': 8, 'level': 1, 'type': True, 'value': 1}, ... {'duration': 128, 'item': 38, 'level': 1, 'type': True, 'value': 1}, {'duration': 145, 'item': 39, 'level': 1, 'type': True, 'value': 1}, {'duration': 135, 'item': 40, 'level': 1, 'type': True, 'value': 1}, {'duration': 154, 'item': 41, 'level': 1, 'type': True, 'value': 1}, {'duration': 1724, 'item': 1, 'level': 2, 'type': True, 'value': 1}, {'duration': 160, 'item': 2, 'level': 2, 'type': True, 'value': 1}, {'duration': 158, 'item': 3, 'level': 2, 'type': True, 'value': 1}, {'duration': 306, 'item': 4, 'level': 2, 'type': True, 'value': 1}, ... {'duration': 176, 'item': 73, 'level': 2, 'type': True, 'value': 1}, {'duration': 151, 'item': 74, 'level': 2, 'type': True, 'value': 1}, {'duration': 178, 'item': 75, 'level': 2, 'type': True, 'value': 1}, {'duration': 161, 'item': 76, 'level': 2, 'type': False, 'value': 0}, {'duration': 5602, 'item': 1, 'level': 3, 'type': True, 'value': 1}, {'duration': 2588, 'item': 1, 'level': 4, 'type': True, 'value': 1}, ... {'duration': 809, 'item': 1, 'level': 15, 'type': True, 'value': 1}], 'timestamp': 1642779164213, 'duration': 78365, 'activity': '8vw829aemgdxy8f1fvk9'} Cats & Dogs​ ActivitySpec: lamp.cats_and_dogs & lamp.cats_and_dogs_new Description​ The Cats and Dogs game. Participants are shown a field of 10 boxes arranged in a fixed random pattern (does not change from test to test), which raise to reveal either an image of a cat, an image of a dog, or neither in a random pattern. Over the course of three levels and 45 trials, participants are told to: Click on all dogs (only dogs and blanks are shown) Click on all dogs (dogs, cats, and blanks are shown) Click on all cats (dogs, cats, and blanks are shown) Settings​ Currently no settings are available for this activity. Data​ static_data: point: The associated point value with the completed session. 2 if all 45 trials were answered perfectly, else 1. correct_answers: The total number of correct answers made in the session. wrong_answers: The total number of incorrect answers made in the session. total_questions: The total number of trials given to the participant. Currently always 45. temporal_slices: item: 1-10 depending on the box chosen value: Unused. type: True if the tap was correct, false otherwise duration: Time elapsed since the last tap or trial start level: 1-3 corresponding to the numbered levels above Example​ {'duration': 445841, 'static_data': {'StartTime': None, 'correct_answers': 22, 'point': 1, 'score': 49, 'type': 1, 'wrong_answers': 1}, 'temporal_slices': [{'duration': 5243, 'item': 9, 'level': 1, 'type': True, 'value': None}, {'duration': 2611, 'item': 5, 'level': 1, 'type': True, 'value': None}, {'duration': 1125, 'item': 8, 'level': 1, 'type': True, 'value': None}, {'duration': 2688, 'item': 2, 'level': 1, 'type': True, 'value': None}, {'duration': 946, 'item': 3, 'level': 1, 'type': True, 'value': None}, {'duration': 1000, 'item': 4, 'level': 1, 'type': True, 'value': None}, {'duration': 4568, 'item': 4, 'level': 1, 'type': True, 'value': None}, {'duration': 1035, 'item': 6, 'level': 1, 'type': True, 'value': None}, {'duration': 843, 'item': 3, 'level': 1, 'type': True, 'value': None}, {'duration': 798, 'item': 2, 'level': 1, 'type': True, 'value': None}, {'duration': 4298, 'item': 1, 'level': 1, 'type': True, 'value': None}, {'duration': 854, 'item': 8, 'level': 1, 'type': True, 'value': None}, {'duration': 1397, 'item': 5, 'level': 1, 'type': True, 'value': None}, {'duration': 885, 'item': 9, 'level': 1, 'type': True, 'value': None}, {'duration': 4338, 'item': 10, 'level': 1, 'type': True, 'value': None}, {'duration': 624, 'item': 9, 'level': 1, 'type': True, 'value': None}, {'duration': 2846, 'item': 3, 'level': 1, 'type': True, 'value': None}, {'duration': 2002, 'item': 8, 'level': 2, 'type': False, 'value': None}, {'duration': 1981, 'item': 5, 'level': 2, 'type': True, 'value': None}, {'duration': 731, 'item': 3, 'level': 2, 'type': True, 'value': None}, {'duration': 4555, 'item': 4, 'level': 2, 'type': True, 'value': None}, {'duration': 1608, 'item': 3, 'level': 2, 'type': True, 'value': None}, {'duration': 910, 'item': 5, 'level': 2, 'type': True, 'value': None}], 'timestamp': 1649447701749, 'activity': 'sjfvrd7jpjyjzbkgwex4'} Emotion Recognition​ ActivitySpec: lamp.emotion_recognition Description​ The Emotion Recognition task. Participants are presented with a random subset of up to 10 images and must identify the emotion expressed in each one (e.g. \"Happiness\", \"Sadness\", \"Neutral\", \"Fear\", \"Anger\"). Settings​ NA. Data​ static_data: NA. temporal_slices: item: Question number. value: Happiness, Sadness, Fear, Anger, Neutral type: False (incorrect); True (correct). duration: Time elapsed in s since last event. level: Question prompt. Example​ {'temporal_slices': [{'duration': 0.833, 'item': 1, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Fear'}, {'duration': 0.798, 'item': 2, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Anger'}, {'duration': 2.354, 'item': 3, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Fear'}, {'duration': 1.407, 'item': 4, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Neutral'}, {'duration': 1.886, 'item': 5, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Neutral'}, {'duration': 1.059, 'item': 6, 'level': 'Which emotion best describes this face?', 'type': True, 'value': 'Neutral'}, {'duration': 0.923, 'item': 7, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Neutral'}, {'duration': 0.948, 'item': 8, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Neutral'}, {'duration': 0.91, 'item': 9, 'level': 'Which emotion best describes this face?', 'type': False, 'value': 'Neutral'}], 'timestamp': 1731005505839, 'date': '2024-11-07 18:51:45.839000', 'game': 'emotion_recognition'} Jewels​ ActivitySpec: lamp.jewels_a & lamp.jewels_b Description​ The Jewels game, with variants A & B. The Jewels game is similar to the Trail-Making Test which measures processing speed and task switching. During the Jewels game, participants view a field of sequentially numbered jewels. In the \"A\" variant, participants click on the jewels in order. In the \"B\" variant, multiple jewel shapes may appear and the user must click on the same-numbered jewels in a predetermined order (e.g. clicking first on a square jewel numbered 1, then a round jewel numbered 1, then a square jewel numbered 2, and so on). Except for the first trial (see Settings below), the maximum number of jewels is 25. The number of shapes will increase up to a maximum of 4. The algorithm that calculates the number of jewels shown (15-25 by default) and shapes shown (1-4 by default) is rather complicated - we recommend leaving the non-timing settings as the default for this reason. Increase Explanation At the end of each successfully completed level a certain number of bonus points is assigned, equal to the remaining time minus 2 times the number of errors made. The running total of bonus points is then divided by the bonus_point_count setting and floored. If the number from step 2 is greater than 1, level-1, divided by the x_changes_in_level_count then multiplied by x_diamond_count is used to determine how many extra jewels should be added, to maximum of 25 total jewels. If level is less than or equal to 1, nothing happens. The same applies for the number of shapes shown, but the maximum number of shapes is 4 and the parameters are y_changes_in_level_count and y_shape_count, respectively. Settings​ mode: (number) Difficulty (1-easy, 4-expert) shape_count:(number) Starting number of shapes, default is 1. Do not set above 8. variant: (string) If set to trails_b, the number of shapes will increase. beginner_seconds: (number) the number of seconds allowed if difficulty is set to 1. intermediate_seconds: (number) the number of seconds allowed if difficulty is set to 2. advanced_seconds: (number) the number of seconds allowed if difficulty is set to 3. expert_seconds: (number) the number of seconds allowed if difficulty is set to 4. diamond_count: (number) starting diamond count (default 15). After the first trial, the max is 25. bonus_point_count: (number) Default is 50. The number of bonus points (remaining time minus errors*2) required to increase the number of jewels or shapes. x_changes_in_level_count: (number) Once enough bonus points are accumulated, changes the number of jewels by x_diamond_count times this (ceiling 25). x_diamond_count: (number) See above. y_changes_in_level_count: (number) Once enough bonus points are accumulated, changes the number of shapes by x_diamond_count times this (ceiling 4). y_shape_count: (number) see above. Data​ static_data: point: (number) The associated point value with the completed session. 1 if the participant timed out on a trial. 2 if they voluntarily returned to the dashboard via the back button. score: (number) The percentage of correct trials, rounded to two decimal places. total_attempts: (number) The total number of attempts made during the session. total_bonus_collected: (number) The total bonus accumulated (time remaining when a trial is finished - 2*errors). Can be negative. total_jewels_collected: (number) The total number of jewels correctly clicked on. temporal_slices: item: (number) The number of the jewel clicked. value: Unused. type: (boolean) Whether the correct item was tapped or not (True or False). duration: (number) Time since the previous jewel was tapped. level: (number) The trial level. Increases by 1 at the start of each new trial unless the accumulated bonus points divided by bonus_point_count is equal to the current level when floored. Example​ The following data is Jewels B Data {'static_data': {'point': 2, 'score': '97.37', 'total_attempts': 76, 'total_bonus_collected': 239, 'total_jewels_collected': 74}, 'temporal_slices': [{'duration': 0, 'item': 1, 'level': 1, 'type': True, 'value': None}, {'duration': 1852, 'item': 2, 'level': 1, 'type': True, 'value': None}, {'duration': 1211, 'item': 3, 'level': 1, 'type': True, 'value': None}, {'duration': 858, 'item': 4, 'level': 1, 'type': True, 'value': None}, {'duration': 954, 'item': 5, 'level': 1, 'type': True, 'value': None}, {'duration': 1892, 'item': 6, 'level': 1, 'type': True, 'value': None}, {'duration': 958, 'item': 7, 'level': 1, 'type': True, 'value': None}, {'duration': 1043, 'item': 8, 'level': 1, 'type': True, 'value': None}, {'duration': 1172, 'item': 9, 'level': 1, 'type': True, 'value': None}, {'duration': 2933, 'item': 10, 'level': 1, 'type': True, 'value': None}, {'duration': 1048, 'item': 11, 'level': 1, 'type': True, 'value': None}, {'duration': 526, 'item': 12, 'level': 1, 'type': True, 'value': None}, {'duration': 573, 'item': 13, 'level': 1, 'type': True, 'value': None}, {'duration': 712, 'item': 14, 'level': 1, 'type': True, 'value': None}, {'duration': 1212, 'item': 15, 'level': 1, 'type': True, 'value': None}, {'duration': 0, 'item': 1, 'level': 1, 'type': True, 'value': None}, {'duration': 1049, 'item': 2, 'level': 1, 'type': True, 'value': None}, {'duration': 2958, 'item': 3, 'level': 1, 'type': True, 'value': None}, {'duration': 1001, 'item': 4, 'level': 1, 'type': True, 'value': None}, {'duration': 832, 'item': 5, 'level': 1, 'type': True, 'value': None}, {'duration': 685, 'item': 6, 'level': 1, 'type': True, 'value': None}, {'duration': 1393, 'item': 7, 'level': 1, 'type': True, 'value': None}, {'duration': 876, 'item': 8, 'level': 1, 'type': True, 'value': None}, {'duration': 701, 'item': 9, 'level': 1, 'type': True, 'value': None}, {'duration': 2651, 'item': 10, 'level': 1, 'type': True, 'value': None}, {'duration': 1554, 'item': 11, 'level': 1, 'type': True, 'value': None}, {'duration': 762, 'item': 12, 'level': 1, 'type': True, 'value': None}, {'duration': 1228, 'item': 13, 'level': 1, 'type': True, 'value': None}, {'duration': 1419, 'item': 14, 'level': 1, 'type': True, 'value': None}, {'duration': 1236, 'item': 15, 'level': 1, 'type': True, 'value': None}, {'duration': 0, 'item': 1, 'level': 2, 'type': True, 'value': None}, {'duration': 3476, 'item': 2, 'level': 2, 'type': True, 'value': None}, {'duration': 1256, 'item': 3, 'level': 2, 'type': True, 'value': None}, {'duration': 6022, 'item': 4, 'level': 2, 'type': True, 'value': None}, {'duration': 3205, 'item': 5, 'level': 2, 'type': True, 'value': None}, {'duration': 742, 'item': 6, 'level': 2, 'type': True, 'value': None}, {'duration': 1890, 'item': 8, 'level': 2, 'type': False, 'value': None}, {'duration': 1563, 'item': 7, 'level': 2, 'type': True, 'value': None}, {'duration': 1069, 'item': 8, 'level': 2, 'type': True, 'value': None}, {'duration': 1113, 'item': 9, 'level': 2, 'type': True, 'value': None}, {'duration': 3184, 'item': 10, 'level': 2, 'type': True, 'value': None}, {'duration': 2339, 'item': 11, 'level': 2, 'type': True, 'value': None}, {'duration': 2521, 'item': 12, 'level': 2, 'type': True, 'value': None}, {'duration': 2564, 'item': 13, 'level': 2, 'type': True, 'value': None}, {'duration': 911, 'item': 14, 'level': 2, 'type': True, 'value': None}, {'duration': 957, 'item': 15, 'level': 2, 'type': True, 'value': None}, {'duration': 919, 'item': 16, 'level': 2, 'type': True, 'value': None}, {'duration': 1579, 'item': 17, 'level': 2, 'type': True, 'value': None}, {'duration': 1281, 'item': 18, 'level': 2, 'type': True, 'value': None}, {'duration': 1215, 'item': 19, 'level': 2, 'type': True, 'value': None}, {'duration': 0, 'item': 1, 'level': 3, 'type': True, 'value': None}, {'duration': 1518, 'item': 1, 'level': 3, 'type': True, 'value': None}, {'duration': 7255, 'item': 2, 'level': 3, 'type': True, 'value': None}, {'duration': 1192, 'item': 2, 'level': 3, 'type': True, 'value': None}, {'duration': 3634, 'item': 3, 'level': 3, 'type': True, 'value': None}, {'duration': 3519, 'item': 3, 'level': 3, 'type': True, 'value': None}, {'duration': 3996, 'item': 4, 'level': 3, 'type': True, 'value': None}, {'duration': 2013, 'item': 4, 'level': 3, 'type': True, 'value': None}, {'duration': 2249, 'item': 5, 'level': 3, 'type': True, 'value': None}, {'duration': 1022, 'item': 5, 'level': 3, 'type': True, 'value': None}, {'duration': 1306, 'item': 6, 'level': 3, 'type': True, 'value': None}, {'duration': 3250, 'item': 6, 'level': 3, 'type': True, 'value': None}, {'duration': 1947, 'item': 7, 'level': 3, 'type': True, 'value': None}, {'duration': 2047, 'item': 8, 'level': 3, 'type': False, 'value': None}, {'duration': 1307, 'item': 7, 'level': 3, 'type': True, 'value': None}, {'duration': 798, 'item': 8, 'level': 3, 'type': True, 'value': None}, {'duration': 718, 'item': 8, 'level': 3, 'type': True, 'value': None}, {'duration': 1371, 'item': 9, 'level': 3, 'type': True, 'value': None}, {'duration': 813, 'item': 9, 'level': 3, 'type': True, 'value': None}, {'duration': 718, 'item': 10, 'level': 3, 'type': True, 'value': None}, {'duration': 924, 'item': 10, 'level': 3, 'type': True, 'value': None}, {'duration': 1834, 'item': 11, 'level': 3, 'type': True, 'value': None}, {'duration': 528, 'item': 11, 'level': 3, 'type': True, 'value': None}, {'duration': 954, 'item': 12, 'level': 3, 'type': True, 'value': None}, {'duration': 832, 'item': 12, 'level': 3, 'type': True, 'value': None}, {'duration': 764, 'item': 13, 'level': 3, 'type': True, 'value': None}], 'duration': 166494, 'activity': 'zezv4mhv2p6v8n60f5dq', 'timestamp': 1650900108188} Maze Task​ ActivitySpec: lamp.maze_game Description​ The Maze task assesses measure motor control and spatial problem solving by having participants tilt their phone to move a ball and complete a series of mazes that increase in diificulty. Settings​ NA. Data​ static_data: NA. temporal_slices: item: ? value: time elapsed in ms type: False (not completed); True (completed). duration: Time elapsed in s since last event. level: ? Example​ {'duration': 62613, 'temporal_slices': [{'duration': 46.909, 'item': 2, 'level': 1, 'type': True, 'value': 46909}, {'duration': 9.596, 'item': 3, 'level': 2, 'type': True, 'value': 9596}, {'type': 'manual_exit', 'value': False}], 'static_data': {}, 'activity': 'r7dyn2cf8qpb09ygtffq', 'timestamp': 1729203092208, '_parent': ''} Pop The Bubbles​ ActivitySpec: lamp.pop_the_bubbles Description​ A sustained attention task where the user is instructed to pop various sequences of bubbles according to varying rulesets. Settings​ bubble_count: number[] = [60, 80, 80]: number of bubbles per level; array length = number of levels, must match below array's length bubble_speed: number[] = [30, 30, 30]: speed at which bubbles enter level in seconds; array length = number of levels, must match above array's length intertrial_duration: number = 0.5: duration between trials, in seconds bubble_duration: number = 1.0: length of time bubbles remain on screen, in seconds Data​ static_data: Unused temporal_slices item: number: the index of the bubble in the current level (Currently bugged: just shows the order of bubbles popped - i.e. the fifth bubble popped will have 5 for this value) value: string: the color of the bubble (i.e. yellow, red, etc.) followed by trial type (i.e. go, no-go, no-go-lure, no-go-constant, no-go-2inrow). type: boolean: whether this tap was correct or incorrect level: number: the level number duration: number: the reaction time to tap the bubble, in milliseconds, or null if bubble ignored (Currently bugged: not present) Example​ {'duration': 46083, 'static_data': {}, 'temporal_slices': [{'item': 1, 'level': 1, 'type': True, 'value': 'blue go'}, {'item': 2, 'level': 1, 'type': True, 'value': 'pink go'}, {'item': 3, 'level': 1, 'type': False, 'value': 'red no-go'}, {'item': 1, 'level': 2, 'type': True, 'value': 'blue go'}, {'item': 2, 'level': 2, 'type': True, 'value': 'yellow go'}, {'item': 3, 'level': 2, 'type': True, 'value': 'blue go'}, {'item': 4, 'level': 2, 'type': True, 'value': 'yellow go'}, {'item': 1, 'level': 3, 'type': True, 'value': 'blue go'}, {'item': 2, 'level': 3, 'type': False, 'value': 'green no-go-constant'}, {'item': 3, 'level': 3, 'type': True, 'value': 'yellow no-go-2inrow'}, {'item': 4, 'level': 3, 'type': True, 'value': 'blue go'}], 'timestamp': 1642777640745, 'activity': '3ztmvcbragc20a6sew4b'} Spatial Span​ ActivitySpec: lamp.spatial_span Description​ The Spatial Span test, with Forward and Backward variants. Participants see a grid of 16 squares (4 x 4) which light up in a specific order. Participants are then told to click, either in the original order (Forward) or reverse order (Backward), the boxes that lit up. Ends after two consecutive sequences where one or more incorrect answers was entered. Settings​ reverse_tapping: (boolean) If true, participants see the Backwards variant. If false, participants get the Forwards variant. Data​ static_data: StartTime: (string) Human readable timestamp of the start of the activity EndTime: (string) Human readable timestamp of the end of the activity point: (number) 2 if every trial was answered correctly, else 1. score: (number) Percentage of stages answered correctly, rounded to 0 decimal spaces. correct_answers: (number) The total number of correct answers made in the session. wrong_answers: (number) The total number of incorrect answers made in the session. type: (number) 1 temporal_slices: item: The index of the box tapped (1-16) (1-4 across the top, 5-8 in the second level from the top, and so on) value: Unused. type: (boolean) Whether the tap was correct or not. duration: (number) Time since previous tap or the beginning of the level. The first duration includes the length of time used to show the sequence of boxes to tap. level: (number) The current level (advances by 1 at the end of each sequence). Example​ {'duration': 48366, 'static_data': {'EndTime': '2022-04-21T17:31:33.825Z', 'StartTime': '2022-04-21T17:30:46.062Z', 'correct_answers': 7, 'point': 1, 'score': 50, 'type': 1, 'wrong_answers': 6}, 'temporal_slices': [{'duration': 5107, 'item': 4, 'level': 1, 'type': True, 'value': None}, {'duration': 876, 'item': 7, 'level': 1, 'type': True, 'value': None}, {'duration': 6024, 'item': 7, 'level': 2, 'type': True, 'value': None}, {'duration': 674, 'item': 12, 'level': 2, 'type': True, 'value': None}, {'duration': 650, 'item': 5, 'level': 2, 'type': True, 'value': None}, {'duration': 8419, 'item': 4, 'level': 3, 'type': False, 'value': None}, {'duration': 706, 'item': 3, 'level': 3, 'type': False, 'value': None}, {'duration': 959, 'item': 13, 'level': 3, 'type': False, 'value': None}, {'duration': 701, 'item': 6, 'level': 3, 'type': True, 'value': None}, {'duration': 7751, 'item': 5, 'level': 3, 'type': False, 'value': None}, {'duration': 728, 'item': 9, 'level': 3, 'type': False, 'value': None}, {'duration': 598, 'item': 10, 'level': 3, 'type': False, 'value': None}, {'duration': 895, 'item': 1, 'level': 3, 'type': True, 'value': None}], 'timestamp': 1650562293825, 'activity': '10rp8he6aa3hqbr5c7v9'} Spin the Wheel​ ActivitySpec: lamp.spin_wheel Description​ Spin the Wheel is based on the Iowa Gambling Task that aims to measure decision-making and risk-taking behavior. Participants start with $2000 and have 20 spins per game by default; to spin the wheel, participants select one of four buttons. Settings​ NA. Data​ static_data: NA. temporal_slices: item: Spin number. value: ? type: Score duration: Time elapsed in s since last event (TODO: remove \"s\"). level: ? Example​ {'duration': 61822, 'temporal_slices': [{'duration': '0s', 'item': 1, 'level': 1, 'type': 2000, 'value': 0}, {'duration': '0.9s', 'item': 2, 'level': 3, 'type': 2100, 'value': 1}, {'duration': '0.897s', 'item': 3, 'level': 4, 'type': 2200, 'value': 1}, {'duration': '0.894s', 'item': 4, 'level': 4, 'type': 1950, 'value': 1}, {'duration': '0.938s', 'item': 5, 'level': 2, 'type': 2000, 'value': 0}, {'duration': '0.892s', 'item': 6, 'level': 3, 'type': 2100, 'value': 1}, {'duration': '0.89s', 'item': 7, 'level': 4, 'type': 2200, 'value': 1}, {'duration': '1.006s', 'item': 8, 'level': 1, 'type': 2200, 'value': 0}, {'duration': '0.91s', 'item': 9, 'level': 2, 'type': 2200, 'value': 0}, {'duration': '0.909s', 'item': 10, 'level': 3, 'type': 2050, 'value': 1}, {'duration': '0.949s', 'item': 11, 'level': 4, 'type': 1800, 'value': 1}, {'duration': '0.938s', 'item': 12, 'level': 4, 'type': 1900, 'value': 1}, {'duration': '0.994s', 'item': 13, 'level': 4, 'type': 1900, 'value': 1}, {'duration': '0.895s', 'item': 14, 'level': 3, 'type': 1900, 'value': 1}, {'duration': '0.886s', 'item': 15, 'level': 1, 'type': 1900, 'value': 0}, {'duration': '0.829s', 'item': 16, 'level': 2, 'type': 1900, 'value': 0}, {'duration': '0.9s', 'item': 17, 'level': 3, 'type': 1650, 'value': 1}, {'duration': '0.944s', 'item': 18, 'level': 4, 'type': 1400, 'value': 1}, {'duration': '0.958s', 'item': 19, 'level': 4, 'type': 1400, 'value': 1}, {'duration': '0.883s', 'item': 20, 'level': 1, 'type': 1400, 'value': 0}, {'type': 'manual_exit', 'value': False}], 'static_data': {}, 'activity': 'g0q7yn340nmjfbh1k694', 'timestamp': 1728688950735, '_parent': ''} Symbol Digit Substitution​ ActivitySpec: lamp.symbol_digit_substitution Description​ Participants are presented with a grid which maps various symbols to digits (digits shown are 1-9). For each successive symbol, participants are required to press the button containing the corresponding digit. Settings​ NA. Data​ static_data: score: number_of_symbols: ? number_of_correct_responses: number_of_incorrect_responses: avg_correct_response_time: avg_incorrect_response_time: temporal_slices: item: NA value: True (correct); False (incorrect). type: ? duration: Time elapsed in s. level: None Example​ {'static_data': {'score': 15, 'number_of_symbols': 30, 'number_of_correct_responses': 29, 'number_of_incorrect_responses': 0, 'avg_correct_response_time': 4, 'avg_incorrect_response_time': 0}, 'temporal_slices': [{'duration': 5.701, 'level': None, 'value': True, 'type': 10}, {'duration': 4.568, 'level': None, 'value': True, 'type': 3}, {'duration': 3.505, 'level': None, 'value': True, 'type': 4}, {'duration': 4.632, 'level': None, 'value': True, 'type': 7}, {'duration': 3.363, 'level': None, 'value': True, 'type': 10}, {'duration': 3.655, 'level': None, 'value': True, 'type': 1}, {'duration': 4.083, 'level': None, 'value': True, 'type': 3}, {'duration': 3.475, 'level': None, 'value': True, 'type': 2}, {'duration': 3.614, 'level': None, 'value': True, 'type': 10}, {'duration': 3.825, 'level': None, 'value': True, 'type': 8}, {'type': 'manual_exit', 'value': False}], 'activity': '3w2a3wrbk9efxb4km8bp', 'timestamp': 1728688811241, 'duration': 122207, '_parent': ''} Coming Soon:​ The following activities are not currently implemented in LAMP but are actively being worked on (or ported, for activities that were available in mindLAMP v1) 3D Figure Copy​ ActivitySpec: lamp.3d_figure_copy Description​ The 3D Figure drawing game. Settings​ Data​ static_data: point: The associated point value with the completed session. drawn_file_name: The link to the file containing the drawn image. game_name: The unique game name for the drawing session. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused. Example​ Digit Span​ ActivitySpec: lamp.digit_span Description​ The Digit Span test, with Forward and Backward variants. Settings​ Data​ static_data: rating: The associated rating of the completed session. score: The computed score for the completed session. correct_answers: The total number of correct answers made in the session. wrong_answers: The total number of incorrect answers made in the session. type: The integer indicating forward or backward variant. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused. Example​ N-Back​ ActivitySpec: lamp.nback & lamp.nback_new Description​ The NBack test. Settings​ Data​ static_data: score: The computed score for the completed session. correct_answers: The total number of correct answers made in the session. wrong_answers: The total number of incorrect answers made in the session. total_questions: The total number of questions encountered during the session. version: The version of the test played. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused. Example​ Serial 7s​ ActivitySpec: lamp.serial_7s Description​ The Serial 7s test. Settings​ Data​ static_data: Unused. rating: The associated rating of the completed session. score: The computed score for the completed session. total_attempts: The total number of attempts made during the session. total_questions: The total number of questions encountered during the session. version: The version of the test played. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused. Example​ Simple Memory​ ActivitySpec: lamp.simple_memory Description​ The Simple Memory test. Settings​ Data​ static_data: score: The computed score for the completed session. correct_answers: The total number of correct answers made in the session. wrong_answers: The total number of incorrect answers made in the session. total_questions: The total number of questions encountered during the session. version: The version of the test played. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused. Example​ Temporal Order​ ActivitySpec: lamp.temporal_order Description​ The Temporal Order test. Settings​ Data​ static_data: rating: The associated rating of the completed session. score: The computed score for the completed session. correct_answers: The total number of correct answers made in the session. wrong_answers: The total number of incorrect answers made in the session. version: The version of the test played. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused. Example​ Trails B​ ActivitySpec: lamp.trails_b & lamp.trails_b_new & lamp.trails_b_dot_touch Description​ The new dot-touch variant of the Trails B test. Settings​ Data​ static_data: point: The associated point value with the completed session. rating: The associated rating of the completed session. score: The computed score for the completed session. total_attempts: The total number of attempts made during the session. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused. Example​ Visual Association​ ActivitySpec: lamp.visual_association Description​ The Visual Association test. Settings​ Data​ static_data: rating: The associated rating of the completed session. score: The computed score for the completed session. total_attempts: The total number of attempts made during the session. total_questions: The total number of questions encountered during the session. version: The version of the test played. temporal_slices: item: Unused. value: Unused. type: Unused. duration: Unused. level: Unused.) Example​ Edit this page Last updated on Nov 19, 2024 by Juan Previous Introduction Next Sensor Types Survey Balloon Risk Cats & Dogs Emotion Recognition Jewels Maze Task Pop The Bubbles Spatial Span Spin the Wheel Symbol Digit Substitution Coming Soon: 3D Figure Copy Digit Span N-Back Serial 7s Simple Memory Temporal Order Trails B Visual Association","s":"Activity Types","u":"/data_science/data_types/activity_types","h":"","p":609},{"i":612,"t":"Deploying LAMP Preparing Resources on AWS On this page Preparing Resources on AWS warning Although AWS is not strictly required, it is highly recommended. If you choose not to use AWS resources, members from the mindLAMP team will not be able to provide support or answer questions. The following instructions will result in a Docker Swarm setup prepared to deploy LAMP. You will need to continue following the instructions after this phase to successfully configure LAMP. Digital Psychiatry's AWS Network Diagram for the LAMP Platform For EC2 Instances Only:​ A HARD requirement for the successful operation of the LAMP Platform is the use of a high performance SSD volume. For more information on these hard limitations and requirements, see the MongoDB documentation here. Required maximum (saturable) disk bandwidth: 4750 Mbps Required maximum disk throughput: 593.75 MB/s Required maximum disk I/O operations: 20000 IOPS Required minimum disk throughput: 125 MB/s Required minimum disk I/O operations: 3000 IOPS Required minimum disk space: 64 GB If using AWS, provisioning a DocumentDB cluster is the simplest way to achieve these baseline requirements for efficient and accurate data collection with no database outages or upload rejections. You must replace the value of MY_DNS_NAME in the commands below. 1. Create an EC2 instance. -> AMI: AWS Linux 2 -> Instance Type: [MINIMUM] t2.medium -> Create a new IAM role with the `AmazonSSMManagedInstanceCore` policy. -> Enable termination protection. -> Create a [RECOMMENDED] 1TB EBS volume WITH encryption enabled. -> Configure security group: -> HTTP: TCP 80 from anywhere -> HTTPS: TCP 443 from anywhere -> Docker Daemon: TCP 2375 from this Security Group -> Docker Machine: TCP 2376 from this Security Group -> Docker Swarm: TCP 2377 from this Security Group -> Docker Swarm: TCP 7946 from this Security Group -> Docker Swarm: UDP 7946 from this Security Group -> Docker Overlay: UDP 4789 from this Security Group -> Create a new key pair and keep it private. -> Allocate and assign an elastic IP to the instance. 2. Run the following commands in the instance. sudo yum -y update && sudo yum -y install docker -y sudo usermod -a -G docker ec2-user sudo hostnamectl set-hostname sudo printf \"[Service]\\nExecStart=\\nExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock\\n\" | sudo tee /etc/systemd/system/docker.service.d/override.conf sudo systemctl daemon-reload && sudo service docker restart sudo docker swarm init 3. Create your DNS binding in Route53. EC2 Commands​ The following is a set of bash commands to be used from within AWS Systems Manager once a new EC2 instance and EBS volume are created with the AWS SSM IAM role. DO NOT USE THIS AS A SCRIPT! THOROUGHLY READ IT AND RUN EACH COMMAND INDIVIDUALLY! SUBSTITUTE ALL VARIABLES BEFORE CONTINUING! # Assumes nvme1n1 is the name of the EBS volume. # Use lsblk to confirm this before running the script. # Attach EBS volume and configure auto-reattach on restart. mkfs -t xfs /dev/nvme1n1 mkdir /data && mount /dev/nvme1n1 /data printf \"\\nUUID=$(blkid -s UUID -o value /dev/nvme1n1) /data xfs defaults,nofail 0 2\" >> /etc/fstab umount /data && mount -a # Install Docker and move Docker root to EBS volume. yum install docker mkdir -p /data/var/lib/docker && ln -s /data/var/lib/docker /var/lib/docker # Set hostname before starting Docker and join the Swarm. hostnamectl set-hostname node-01.example.com service docker start docker swarm join --token SWARM_TOKEN IP_ADDR:2377 In case your EBS volume runs out of storage space, follow the instructions below: # expand the EBS volume using the AWS management console first lsblk growpart /dev/nvme1n1 1 xfs_growfs -d /data AWS SSM Instructions​ We recommend disabling all SSH (port 22) or remote access to any EC2 instances you configure. Use AWS Systems Session Manager (AWS SSM) to access your node. Additionally, follow the instructions below on your local computer to securely communicate with the instance(s). Install the AWS CLI SSM plugin. Configure SSH to support AWS SSM tunneling. Alternatively, manually open a port forwarding tunnel. aws ssm start-session \\ --target $(aws ec2 describe-instances \\ --filter \"Name=tag:Name,Values=node-01\" \\ --query \"Reservations[].Instances[?State.Name == 'running'].InstanceId[]\" \\ --output text) \\ --document-name AWS-StartPortForwardingSession \\ --parameters '{ \"portNumber\": [\"22\"], \"localPortNumber\": [\"9999\"] }' Alternatively, manually open a secure SSH tunnel session. aws ssm start-session \\ --target $(aws ec2 describe-instances \\ --filter \"Name=tag:Name,Values=node-01\" \\ --query \"Reservations[].Instances[?State.Name == 'running'].InstanceId[]\" \\ --output text) \\ --document-name AWS-StartSSHSession \\ --parameters 'portNumber=%p' Using AWS DocumentDB instead of MongoDB (Coming Soon)​ The Division of Digital Psychiatry has been working closely with Solutions Architects at Amazon Web Services (AWS) to improve performance and reliability, as well as reduce maintenance overhead and IT skills required for deployment. For this reason, we support MongoDB in addition to the Apache CouchDB database. AWS offers a managed solution for MongoDB databases called DocumentDB that abstracts and simplifies all MongoDB database setup and operations needs, including routine backups and HIPAA-compliant encryption of data at rest and in transit. DocumentDB is a high performance database solution built on the AWS Aurora technology that supports global replicated clusters that span across multiple regions (i.e. U.S. East and Mumbai, for example) and up to 15 read replicas in a single region. This provides high availability and performance for the LAMP API and in turn the clinical dashboard and mobile apps that are built upon it. This advanced technology and other AWS managed solutions are natively integrated into the LAMP Platform and the Cortex data analysis toolkit, enabling both advanced clinical care management features (such as just-in-time adaptive interventions) and advanced research/data analysis methods. We are working closely with Amazon Web Services (AWS) to bring this feature to all organizations using the LAMP Platform. If you or your organization are interested, please contact us. Edit this page Last updated on Nov 19, 2024 by Juan Previous Provisioning the LAMP Platform Next Deploying via CloudFormation For EC2 Instances Only: EC2 Commands AWS SSM Instructions Using AWS DocumentDB instead of MongoDB (Coming Soon)","s":"Preparing Resources on AWS","u":"/deploy/aws","h":"","p":611},{"i":614,"t":"Deploying LAMP Deploying via CloudFormation On this page Deploying via CloudFormation Validate​ aws cloudformation validate-template \\ --region us-east-2 \\ --template-body file://cloudformation.yaml Create​ aws cloudformation create-stack \\ --region us-east-2 \\ --stack-name LAMP \\ --template-body file://cloudformation.yaml \\ --capabilities CAPABILITY_NAMED_IAM \\ --parameters HostedZoneId=YOUR_HOSTED_ZONE_HERE,DomainName=YOUR_DOMAIN_NAME_HERE,InstanceType=t3.medium,ImageId=ami-0f57b4cec24530068,VpcCidrBlock=10.0.0.0/16,SubnetCidrBlock=10.0.0.0/24,KeyName=YOUR_KEY_NAME_HERE,SecurityGroupName=mindLAMP-platform-ec2-sg,SshCidrBlock=52.95.4.0/24,Ec2Instance01Name=mindLAMP-platform-ec2-01,Ec2Instance02Name=mindLAMP-platform-ec2-02 Update​ aws cloudformation update-stack \\ --region us-east-2 \\ --stack-name LAMP \\ --template-body file://cloudformation.yaml \\ --capabilities CAPABILITY_NAMED_IAM \\ --parameters HostedZoneId=YOUR_HOSTED_ZONE_HERE,DomainName=YOUR_DOMAIN_NAME_HERE,InstanceType=t3.medium,ImageId=ami-0f57b4cec24530068,VpcCidrBlock=10.0.0.0/16,SubnetCidrBlock=10.0.0.0/24,KeyName=YOUR_KEY_NAME_HERE,SecurityGroupName=mindLAMP-platform-ec2-sg,SshCidrBlock=52.95.4.0/24,Ec2Instance01Name=mindLAMP-platform-ec2-01,Ec2Instance02Name=mindLAMP-platform-ec2-02 Delete​ aws cloudformation delete-stack \\ --region us-east-2 \\ --stack-name LAMP Edit this page Last updated on Nov 19, 2024 by Juan Previous Preparing Resources on AWS Next Deploying the LAMP Platform Validate Create Update Delete","s":"Deploying via CloudFormation","u":"/deploy/cloudformation","h":"","p":613},{"i":616,"t":"Cortex & API Preparing to Analyze Your Data in R On this page Preparing to Analyze Your Data in R If you'd like to follow along with this tutorial but don't have an R development environment set up, consider using RStudio Cloud, a free service from the RStudio team. The majority of the code and directions in this page are now deprecated and integrated in the LAMP API. See 'Preparing to Analyze Your Data in Python' for up-to-date data analysis steps. Connect to your LAMP server.​ First, install the LAMP client library. install.packages(\"devtools\") devtools::install_github('BIDMCDigitalPsychiatry/LAMP-r') Then connect to the LAMP API. Your Researcher ID comes from the dashboard at dashboard.lamp.digital. library(LAMP) LAMP <- LAMP$new('https://api.lamp.digital', 'your_email_here@email.com', 'your_password_here') researcher_id <- \"YOUR_RESEARCHER_ID\" Download data from the LAMP server.​ First, download all Participants and retrieve the ID mapping for all Activities in our Study. library(dplyr) library(anytime) library(data.table) participants <- LAMP$Participant$allByStudy(researcher_id) %>% pull(id) activity_map <- LAMP$Activity$allByStudy(researcher_id) %>% dplyr::select(id,name) %>% rename(activity = id) Now we run some pre-processing to flatten the nested data structure that we receive from the ActivityEvent API for each Participant, performed in a loop over all Participants in our Study. Because some entries may be null (missing or invalid), we ignore those and flatten the data after converting time stamps from the UNIX Epoch standard to the human-readable YYYY-MM-DD format. There’s a workaround for excessively-nested survey items as well. The below section of code is now deprecated and integrated into the LAMP API. data_list <- list() for (i in 1:length(participants)) { tmp <- LAMP$ActivityEvent$allByParticipant(participants[i]) if (length(tmp) > 0) { tmp <- right_join(activity_map %>% select(activity, name), jsonlite::flatten(tmp) %>% mutate(timestamp = anytime(as.numeric(timestamp)/1000, tz = \"America/New_York\")) %>% rename(activity_duration = duration) %>% mutate(id = participants[i]), by=\"activity\") tmp_event_list <- list() for (j in 1:nrow(tmp)) { if (length(tmp[j,]$temporal_events[[1]]) > 0) { tmp_event_list[[j]] <- cbind(tmp[j,], tmp[j,]$temporal_events[[1]], row.names=F) %>% dplyr::select(-temporal_events) } } data_list[[i]] <- rbindlist(tmp_event_list, fill = T) } } data_list[sapply(data_list, is.null)] <- NULL Now, we combine the data frames we’ve pre-processed and ensure they follow the proper data format. Once we reorder the columns to include only variables of interest, we can call the head() function to preview the data frame. To view all available variables in your data frame, use colnames(result_events_mod). Some of the columns we’re selecting tell us about meta information about the Activity (such as whether it’s a survey or game), the individual survey question or game level results, and other optional game data (static_data, which may include NA values). To learn more about what each of these columns contains, represents, and can be used for, please see the help topic. result_events <- rbindlist(data_list, fill = T) %>% mutate(id = as.character(id)) %>% mutate(activity = as.character(activity)) %>% mutate(name = as.character(name)) head(results) Code Output​ id timestamp name item value 1 U1094374134 2019-12-08 PHQ-8 How often did you feel bad about yourself, or that you were a failure or let your family down? 1 2 U1094374134 2019-12-08 PHQ-8 How often did have you have trouble concentrating on things such as reading or watching tv? 1 3 U1094374134 2019-12-08 PHQ-8 How often did you find yourself moving so slowly, or so fidgety/restless, that others noticed? 1 4 U1094374134 2019-12-08 PHQ-8 How often did you have trouble falling or staying asleep, or sleep for more hours than you meant to? 1 5 U1094374134 2019-12-08 PHQ-8 How often did you feel tired or like you had little energy? 1 6 U1094374134 2019-12-08 PHQ-8 How often did you find yourself with no appetite, or eating more than you meant to? 1 Optional: Output the data to a CSV.​ write.csv(results, \"./output-1-27-20.csv\", row.names = F) Appendix: Sample Analyses Check out all the activities in the study​ This includes both default activities and custom activities. activity_map %>% select(activity, spec, name) Code Output​ ## activity spec name ## 1 QWN0aXZpdHk6MDoxMDM6MjM~ lamp.group Daily Survey Check-In ## 2 QWN0aXZpdHk6MToxMDM6MzIw lamp.survey PHQ-8 ## 3 QWN0aXZpdHk6MToxMDM6MzQx lamp.survey Instructions ## 4 QWN0aXZpdHk6MToxMDM6MzQy lamp.survey GAD-7 ## 5 QWN0aXZpdHk6MToxMDM6MzQz lamp.survey PIU-SF-6 ## 6 QWN0aXZpdHk6MToxMDM6MzQ0 lamp.survey Warning ## 7 QWN0aXZpdHk6MToxMDM6MzQ1 lamp.survey Qualitative Digital Media Use Assessment ## 8 QWN0aXZpdHk6MToxMDM6MzQ2 lamp.survey Screen Time Use - iPhones only ## 9 QWN0aXZpdHk6MToxMDM6MzQ3 lamp.survey iPhone/Android Assessment ## 10 QWN0aXZpdHk6MjoxMDM6MA~~ lamp.nback N-Back ## 11 QWN0aXZpdHk6MzoxMDM6MA~~ lamp.trails_b Trails B ## 12 QWN0aXZpdHk6NDoxMDM6MA~~ lamp.spatial_span Spatial Span ## 13 QWN0aXZpdHk6NToxMDM6MA~~ lamp.simple_memory Simple Memory ## 14 QWN0aXZpdHk6NjoxMDM6MA~~ lamp.serial7s Serial 7s ## 15 QWN0aXZpdHk6NzoxMDM6MA~~ lamp.cats_and_dogs Cats and Dogs ## 16 QWN0aXZpdHk6ODoxMDM6MA~~ lamp.3d_figure_copy 3D Figure Copy ## 17 QWN0aXZpdHk6OToxMDM6MA~~ lamp.visual_association Visual Association ## 18 QWN0aXZpdHk6MTA6MTAzOjA~ lamp.digit_span Digit Span ## 19 QWN0aXZpdHk6MTE6MTAzOjA~ lamp.cats_and_dogs_new Cats and Dogs New ## 20 QWN0aXZpdHk6MTI6MTAzOjA~ lamp.temporal_order Temporal Order ## 21 QWN0aXZpdHk6MTM6MTAzOjA~ lamp.nback_new N-Back New ## 22 QWN0aXZpdHk6MTQ6MTAzOjA~ lamp.trails_b_new Trails B New ## 23 QWN0aXZpdHk6MTU6MTAzOjA~ lamp.trails_b_dot_touch Trails B Dot Touch ## 24 QWN0aXZpdHk6MTY6MTAzOjA~ lamp.jewels_a Jewels Trails A ## 25 QWN0aXZpdHk6MTc6MTAzOjA~ lamp.jewels_b Jewels Trails B ## 26 QWN0aXZpdHk6MTg6MTAzOjA~ lamp.scratch_image Scratch Image ## 27 QWN0aXZpdHk6MTk6MTAzOjA~ lamp.spin_wheel Spin Wheel Get number of participants in the study​ print(paste(\"Number of Participants:\", length(participants))) Code Output​ ## [1] \"Number of Participants: 29\" Get engagement and plot activity histogram​ engagement_data <- inner_join(results %>% dplyr::count(id), results %>% group_by(id) %>% filter(row_number()==n()) %>% select(id, timestamp), by=\"id\") %>% rename(activities.completed = n) %>% rename(most.recent.activity = timestamp) engagement_data Code Output​ ## # A tibble: 27 x 3 ## id activities.completed most.recent.activity ## ## 1 U1005979819 659 2019-11-16 22:50:57 ## 2 U1094374134 2085 2019-08-14 12:23:15 ## 3 U1126469507 503 2019-12-10 21:52:20 ## 4 U1232915366 226 2020-01-29 00:51:34 ## 5 U1235780769 767 2019-12-09 20:08:02 ## 6 U1367615199 813 2019-11-13 16:11:09 ## 7 U1500960001 742 2019-10-25 21:26:24 ## 8 U1680931766 1070 2019-12-13 22:41:58 ## 9 U176381486 585 2019-11-08 18:45:24 ## 10 U2127860149 170 2019-11-13 16:51:52 ## # … with 17 more rows Let's view a histogram representation of the data. hist(engagement_data$activities.completed, breaks=15) Code Output​ ![../Topics/Preparing to analyze your data in R/Untitled.png](../Topics/Preparing to analyze your data in R/Untitled.png) Get mean and standard deviation for any survey scale​ We’ll include only anxiety survey (GAD-7) results and parse/convert their answer data to numbers using the readr library. Then, we aggregate by timestamp (which is unique to each Activity), and summarize the table. library(readr) data <- results %>% filter(name == \"GAD-7\") %>% mutate(value = as.numeric(parse_number(as.character(value)))) %>% group_by(id,timestamp) %>% summarise(average_GAD = mean(value)) summary(data$average_GAD) Code Output​ ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 0.0000 0.4286 0.8571 0.9139 1.4286 3.0000 print(paste(\"Mean GAD-7 across all participants:\", round(mean(data$average_GAD), 3), \"±\", round(sd(data$average_GAD), 3))) Code Output​ ## [1] \"Mean GAD-7 across all participants: 0.914 ± 0.667\" Plot survey scores over time for an individual participant​ Filter the first Participant’s mood (PHQ-8) results and parse the strings into numbers as they may be either numeric or text. Then, we aggregate by timestamp, which is unique for each Activity, and take the mean of all scores for a given timestamp. data <- results %>% filter(id == participants[1] & name == \"PHQ-8\") %>% mutate(value = as.numeric(as.character(value))) %>% group_by(timestamp) %>% summarise(average_score = mean(value)) Plot the now-filtered data using the ggplot2 library; you’ll find our sample graph below. library(ggplot2) ggplot(data, aes(x = timestamp, y = average_score)) + geom_line(size=1, color=\"steelblue\") + theme_minimal(base_size = 15) + ylim(0,4) + theme( panel.grid.major = element_blank(), panel.background = element_blank(), axis.line = element_line(colour = \"black\"), axis.title.x = element_text(size = 15)) Compare self-reported anxiety with self-reported problematic internet use​ First, we filter data, using a left-join (which is like a merge operation) between the GAD-7 and PIU-6 survey instruments, such that each participant is a single row. All answer data is converted to numeric values first, and then we aggregate by ID, which is unique to each Activity. Finally, we take the mean of all scores for a given timestamp. library(tidyr) library(Hmisc) data <- left_join(results %>% filter(name == \"GAD-7\") %>% mutate(value = as.numeric(parse_number(as.character(value)))) %>% group_by(id) %>% summarise(average_GAD = mean(value)), results %>% filter(name == \"PIU-SF-6\") %>% mutate(value = as.numeric(parse_number(as.character(value)))) %>% group_by(id) %>% summarise(average_PIU = mean(value)), by=\"id\") Now, do a regression fit on the filtered data. fit <- lm(average_PIU ~ average_GAD, data = drop_na(data)) Plot the now-filtered data; you’ll find our sample graph below. (drop_na() removes rows with one or more NA values.) ggplot(drop_na(data), aes(x = average_GAD, y = average_PIU)) + geom_point() + geom_smooth(method = 'lm', formula = y~x) + # From https://sejohnston.com/2012/08/09/a-quick-and-easy-function-to-plot-lm-results-in-r/ labs(title = paste(\"Adj R2 = \",signif(summary(fit)$adj.r.squared, 5), \"Intercept =\",signif(fit$coef[[1]],5 ), \" Slope =\",signif(fit$coef[[2]], 5), \" P =\",signif(summary(fit)$coef[2,4], 5)), x = \"Average GAD-7\", y = \"Average PIU-SF-6\") + theme_minimal(base_size = 12) + theme( panel.grid.major = element_blank(), panel.background = element_blank(), axis.line = element_line(colour = \"black\"), axis.title.x = element_text(size = 12)) Edit this page Last updated on Nov 19, 2024 by Juan Previous Preparing to Analyze Your Data in Python Next Cortex Quick Start Guide Connect to your LAMP server. Download data from the LAMP server. Code Output Optional: Output the data to a CSV. Check out all the activities in the study Code Output Get number of participants in the study Code Output Get engagement and plot activity histogram Code Output Code Output Get mean and standard deviation for any survey scale Code Output Code Output Plot survey scores over time for an individual participant Compare self-reported anxiety with self-reported problematic internet use","s":"Preparing to Analyze Your Data in R","u":"/data_science/r","h":"","p":615},{"i":618,"t":"Deploying LAMP Configure OAuth for Google Configure OAuth for Google For Oauth integration more broadly, please follow the documentation linked here: https://docs.lamp.digital/develop/oauth_oidc/ Configure the Google Cloud App for MindLAMP: To use Google OAuth we’ll need to generate credentials for MindLAMP Create a Project in Google Cloud App as explained here: https://developers.google.com/identity/protocols/oauth2/web-server#enable-apis Create an OAuth Client in the Credentials section as explained here: https://developers.google.com/identity/protocols/oauth2/web-server#creatingcred a. Note that you’ll need to add the dashboard url in the authorized urls. (FE: https://dashboard.lamp.digital) b. As redirect url you’ll need to add the OAuth entry point of the app. That’s the dashboard url followed by “/oauth”. (FE: https://dashboard.lamp.digital/oauth) Copy the client id and the client secret as we’ll need the to configure the server. Configure OAuth in the MindLAMP server: Now that we have the credentials we’ll need to add a few environment variables to the MindLAMP server. OAUTH=\"on\" OAUTH_AUTH_URL=\"https://accounts.google.com/o/oauth2/v2/auth\" OAUTH_TOKEN_URL=\" https://oauth2.googleapis.com/token \" OAUTH_CLIENT_ID=\"client id here\" OAUTH_CLIENT_SECRET=\"client secret here\" OAUTH_REDIRECT_URI=\"dashboard URL here/oauth\" OAUTH_SCOPE=\"https://www.googleapis.com/auth/userinfo.email\" TOKEN_SECRET=\"LAMP defined secret here\" Remember that OAUTH_REDIRECT_URI must be exactly the same as the redirect URI the client was set up with. Edit this page Last updated on Nov 19, 2024 by Juan Previous Complex Password Requirements Next Configuring your server to add Sensors and Activities","s":"Configure OAuth for Google","u":"/deploy/configure_oauth_google","h":"","p":617},{"i":620,"t":"Cortex & API Tags & Attachments On this page Tags & Attachments Overview To offer a way to store persistent, easily accessible data, the LAMP platform has implemented a feature known as attachments (sometimes also called tags). You can use tags to store any json-formatted data. Using this feature, you can attach data to any element of LAMP including: Participants Studies Researchers Activities Functions​ There are three main functions used to interact with LAMP attachments, that allow you to list, view, and set attachments. In order, they are: LAMP.Type.list_attachments('id')​ Given a LAMP id, this function returns an array of strings. Each string corresponds to a tag that has been set on the target. For example: LAMP.Type.list_attachments(\"ffmz65mn1gtav5fq3bhq\")['data'] ['graphs.data_quality.activity_counts', 'graphs.data_quality.passive_features', 'graphs.data_quality.quality_tags', 'lamp.attachment_test', 'lamp.dashboard.credential_roles', 'lamp.dashboard.researcher_tags', 'lamp.dashboard.user_type', 'lamp.test'] LAMP.Type.get_attachment('id','tag_name')​ Given a LAMP id and an existing tag, this function returns the currently set value of the tag. It returns a 404 error if the tag is not set. If the same tag has been set multiple times by different agents, (e.g. both a Researcher and a Study), the tag belonging to the highest authority (e.g. Researcher over Study) is returned. For more information on this, see Authority below. LAMP.Type.get_attachment(\"ffmz65mn1gtav5fq3bhq\",'lamp.test')['data'] {'test_data_key': 21283, 'my_list_of_data': [\"Android\", \"iOS\"]} LAMP.Type.set_attachment('parent','target','tag_name','body')​ This function is used to set the value of a tag. 'Target' here is the LAMP element the tag will be attached to - while 'parent' is the agent setting the tag (such as a Researcher, Study, or even a Participant). An element can also use the shorthand 'me' to set a tag on itself - e.g. a Researcher targeting themself. This function can also be used to delete a tag by setting body as None. LAMP.Type.set_attachment(\"ffmz65mn1gtav5fq3bhq\",'U0591253803','lamp.test','This is a test tag')['data'] LAMP.Type.get_attachment('U0591253803','lamp.test')['data'] 'This is a test tag' LAMP.Type.set_attachment(\"ffmz65mn1gtav5fq3bhq\",\"me\",'lamp.test','This is also a test tag')['data'] LAMP.Type.get_attachment(\"ffmz65mn1gtav5fq3bhq\",'lamp.test')['data'] 'This is also a test tag' Authority​ LAMP does not restrict the setting of a tag even if it has already been set. If the tag was previously set by the same parent, it will be overwritten (or deleted if set to None). If the same tag has been set on the same target, but by multiple users, e.g. by both a Researcher and a Study, both will be present in the database, but only the one set by the highest authority(see below) user will be returned from LAMP.Type.get_attachment. In descending order, authorities are: Admin Researcher Study Participant If a tag set by a higher authority user is later deleted, however, a tag set by a lower authority user will become available again. Case Example 1: Conflicting Tags​ In the following code block, both \"ffmz65mn1gtav5fq3bhq\" (a Researcher), and 'dynp0g0530xkahnzh0xc' (a Study) attempt to set the lamp.test tag on the user 'U0591253803'. Both tags are successfully set and no error is thrown. However, since the Researcher has a higher authority than the Study, the tag set by the Researcher is returned (even though the tag set by the Study was set later). LAMP.Type.set_attachment(\"ffmz65mn1gtav5fq3bhq\",'U0591253803','lamp.test','Set by Researcher')['data'] LAMP.Type.set_attachment('dynp0g0530xkahnzh0xc','U0591253803','lamp.test','Set by Study')['data'] LAMP.Type.get_attachment('U0591253803', 'lamp.test')['data'] 'Set by Researcher' Case Example 2: Removing a conflict​ In the following code block, both \"ffmz65mn1gtav5fq3bhq\" (a Researcher), and 'dynp0g0530xkahnzh0xc' (a Study) attempt to set the lamp.test tag on the user 'U0591253803'. As before, since the Researcher has a higher authority than the Study, the tag set by the Researcher is returned (even though the tag set by the Study was set later). However, the Researcher tag is then removed, and the tag set by the Study is now the one returned by the API LAMP.Type.set_attachment(\"ffmz65mn1gtav5fq3bhq\",'U0591253803','lamp.test','Set by Researcher')['data'] LAMP.Type.set_attachment('dynp0g0530xkahnzh0xc','U0591253803','lamp.test','Set by Study')['data'] LAMP.Type.get_attachment('U0591253803', 'lamp.test')['data'] 'Set by Researcher' LAMP.Type.set_attachment(\"ffmz65mn1gtav5fq3bhq\",'U0591253803','lamp.test',None)['data'] LAMP.Type.get_attachment('U0591253803', 'lamp.test')['data'] 'Set by Study' Edit this page Last updated on Nov 19, 2024 by Juan Previous Using the LAMP Data Portal Next Admin Checklist Functions LAMP.Type.list_attachments('id') LAMP.Type.get_attachment('id','tag_name') LAMP.Type.set_attachment('parent','target','tag_name','body') Authority Case Example 1: Conflicting Tags Case Example 2: Removing a conflict","s":"Tags & Attachments","u":"/data_science/tags","h":"","p":619},{"i":622,"t":"Deploying LAMP Costs of Deploying the LAMP Platform On this page Costs of Deploying the LAMP Platform The components of the LAMP Platform rely on IT infrastructure that can be self-hosted by your organization (sometimes called \"on-prem\") or hosted by a cloud provider such as Amazon or Google. If you'd like to deploy your organization's instance of the LAMP Platform on a cloud provider, please consult with your legal and IT departments first, and always ensure that you have signed a Business Associate Agreement (BAA) with the cloud provider to comply with HIPAA. Factors that Influence Provisioning of Compute and Storage Resources.​ There are a few factors that need to be accounted when determining how to deploy the components explained above, as well as how high your monthly costs may be. Computing: The components of the LAMP Platform are highly efficient and won't need much computing power; however, at minimum they require a single dual-core node with at least 2 gigabytes of memory. Storage: The data collection rate for the LAMP Platform varies significantly depending on usage needs, spanning from a minimum of 250 gigabytes of low-throughput (HDD) storage to a recommended 4 terabytes of high-throughput (SSD) storage. If you are collecting digital phenotyping data, using the integrated development environments, or scheduling intervention delivery/data analysis scripts, the minimum requirements WILL NOT be sufficient. Network: The network bandwidth of the LAMP Platform varies significantly depending on your organization's size and study/clinic requirements; at minimum you must have single virtual private endpoint (i.e. firewall) with a bandwidth of at least 1 Gbps, to a recommended 10 Gbps to adequately handle sustained multi-user loads. In all cases, the most costly and intensive part of deploying and maintaining the LAMP Platform will be storing the data. Example Use-Cases and Their Associated Cloud Computing Costs.​ When hosting the LAMP Platform with a cloud provider, your monthly costs may vary significantly based on the requirements explained previously. Here are two example configurations with the Amazon Web Services (AWS) cloud provider: \"I run a digital clinic with about ~15 patients and don't intend to use advanced features such as digital phenotyping (sensor data) collection or Automations.\" Computing: 1 node, 2 vCPU, 2 GB RAM Storage: 250 GB, no snapshots Network: Up to 10 Gbps Total Cost: ~$35.00/mo \"I run multiple research studies with 200+ patients and intend to collect digital phenotyping data at a high frequency, develop and use machine learning algorithms through the Automations framework, and more advanced features.\" Computing: 2 nodes, 16 vCPU, 32 GB RAM Storage: 8.0 TB, automated monthly snapshots Network: 25 Gbps Total Cost: ~$1,500.00/mo Please note that it is currently not yet possible to configure specific sensors to operate at specific frequencies. This feature is coming soon but not available today. Specification vCPU RAM (GB) SSD (TB) EBS EC2 S3 Data Transfer Total Monthly Total Yearly \"10 participants, active only\" 2 (t3.small) 2 0.5 50 13.72 0 0.48 64.2 770.4 \"100 participants, active only\" 2 (t3.small) 2 0.5 50 13.72 0 2.06 65.78 789.36 \"1000 participants, active only\" 2 (t3.small) 2 1 102.4 13.72 0 2.06 118.18 1418.16 \"10 participants, active + passive\" 4 (c5.large) 8 1 102.4 124.1 23.56 5.12 255.18 3062.16 \"100 participants, active + passive\" 4 (c5d.large) 16 2 204.8 186.4 23.56 10.24 425 5100.000000000001 1000 participants active + passive 8 (c5d.2xlarge) 32 4 409.6 248.2 23.56 20.48 701.84 8422.079999999998 When self-hosting the LAMP Platform (that is, \"on-prem\"), it's difficult to determine the monthly costs and maintenance needs. Please reach out to us for a consultation if you or your organization would like assistance with self-hosting. Though self-hosting may appear to be cheaper, the \"hidden costs\" should not be neglected in: ensuring redundant storage, no system down-time, regular storage backups, HIPAA-compatible encryption during flight and at rest, preventing network bottlenecks, regular system maintenance, and more. We do not recommend self-hosting unless your organization already has the infrastructure to correctly do so. Edit this page Last updated on Nov 19, 2024 by Juan Previous Deployment Recommendations Next Provisioning the LAMP Platform Factors that Influence Provisioning of Compute and Storage Resources. Example Use-Cases and Their Associated Cloud Computing Costs.","s":"Costs of Deploying the LAMP Platform","u":"/deploy/costs","h":"","p":621},{"i":624,"t":"Deploying LAMP Complex Password Requirements On this page Complex Password Requirements How it Works​ A new Tag lamp.dashboard.security_preferences must be set by the system administrator to add support to control certain user account creation settings. Currently, we support password rules specified as valid regular expressions (use RegExR or a similar tool to test these). For example, an expression such as ^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*$ matches: ^.* ... .*$ = The entire string must match the expression, and cannot contain line breaks (\\n). (?=.{8,}) = Minimum of 8 characters. (?=.*[a-z]) = Must contain lowercase letters. (?=.*[A-Z]) = Must contain uppercase letters. (?=.*[0-9]) = Must contain numeric digits. Additional parameters (such as required special characters, etc.) can also be added to the regular expression. When setting a password on any user account across LAMP, this system-level Tag is referenced first to confirm the complexity of the password. If no such Tag exists, any password of any complexity with any characters is permitted. If such a Tag exists, but the password_rule is missing or not a valid regular expression, any password of any complexity with any characters is permitted. If such a Tag exists, and the password_rule is a valid regular expression, the password text field in the UI validates the text input by the user against the regular expression. i. If the text matches the regular expression, the password is accepted and the dialog is allowed to proceed. ii. If the text does NOT match the regular expression, the password is not accepted, and the dialog (and its continue button) is disabled until the text is modified to match the regular expression. (An error message is displayed under the text field to inform the user.) Usage​ You can enable this feature from the command line once your server is configured. curl -u admin -L -X PUT 'https:///type/null/tag/lamp.dashboard.security_preferences/me' \\ -H 'Content-Type: application/json' \\ -H 'Accept: application/json' \\ --data-raw '{ \"password_rule\": \"^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*$\" }' You can also use the Python lamp-core library to set the password rule. rule = { \"password_rule\": \"^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*$\" } LAMP.Type.set_attachment(\"null\", 'me', 'lamp.dashboard.security_preferences', rule) caution If the version of the dashboard you use does not respect complex passwords (version 2022.4.x and newer) then users will be allowed to create insecure passwords. Please ensure your organization uses the latest versions of both server AND dashboard. Notably, simple passwords written prior to implementing complex password protocols will still work. caution Upon initially creating a user account, user password will be automatically generated in the default format, regardless of password rules. I.e. a user given the account U1338759043@lamp.com will automatically be given the password U1338759043 regardless of password complexity settings. Edit this page Last updated on Nov 19, 2024 by Juan Previous Troubleshooting Deployment Next Configure OAuth for Google How it Works Usage","s":"Complex Password Requirements","u":"/deploy/passwords","h":"","p":623},{"i":626,"t":"Deploying LAMP Prerequisites for Deploying the LAMP Platform Prerequisites for Deploying the LAMP Platform The mindLAMP app interfaces with the much broader LAMP Platform to provide all of the functionality and features you can interact with within the app. The LAMP Platform is open source and its components are detailed below; to see technical materials such as source code or compiling/testing routines, please visit the components' corresponding repository. There are different ways for your organization to self-deploy the LAMP Platform, and because these components are interoperable, your organization has the choice between only self-deploying one, a combination, or all of these components together. → Be sure to open the toggles on the left-hand side to learn more about what each component does. CORE SERVICE To deploy mindLAMP and to receive support from BIDMC, we require all interested parties to use the Core Service. Cores are referred to as “specialized service facilities,” where they are work units that provide goods and services that facilitate research activity by providing scientific services and resources, both internal and external. Operating expenses are charged to research cores then recovered through user fees charged. The mindLAMP Core provides a way for users to help support to upkeep and maintenance of the software while receiving user support. No data sharing is necessary if mindLAMP is to be hosted outside of BIDMC. If desired and with a data sharing agreement, the mindLAMP Core can help support data hosting. Backend Database The noSQL databases used for modern sensor data collection are CouchDB and MongoDB. Data backup must be manually configured as different organizations will expect different sizes and frequency of data storage, along with variance in data policies. These database components are not built or maintained as part of the LAMP Platform but are required for its usage. Server The server acts as an event bus that connects the different components of the Platform together on the data plane and provides a control plane. It vends the LAMP Application Programming Interface (API) by which clients connect to and use the LAMP Platform. The API enables data harmonization, synchronization, and integration with other platforms and databases through a standardized data format and set of actions with built-in credential management. The API is defined using OpenAPI and JSONSchema to markup extensible interfaces. The industry encryption standards AES-256 and TLSv1.3 facilitate secure storage and transmission of data in a HIPAA, COPPA, and GDPR-compliant manner. Service Worker This component allows external apps and tools to be notified of changes to data from other users through sent notifications and events. This component schedules push notifications to be delivered to mobile devices, as well as manages email/SMS notification delivery. Optionally, it also schedules and executes scripts written in Python, Javascript, or R, as part of intervention delivery and data analysis. This feature can be disabled. When: If your organization is required to ensure that all data is securely managed and complies with internal policies or regulations. Prerequisites: Your organization will need to provision computing resources and encrypted snapshot storage and dedicate personnel to maintenance, updates, and security (i.e. data breach detection). Options: You can use a Backend hosted by your institution with your customized Native App or Frontend or the current Division of Digital Psychiatry version. Frontend App UI The user interface for the mindLAMP app, accessible from the Web, iOS, and Android. For creating and using cognitive tests or other activities, please see the LAMP-activities repository. This component allows administrators, researchers, clinicians, participants, and patients to access and manage their mindLAMP configuration and data. It displays visualizations and can configure clinics and studies to specified requirements, and makes available activities and interventions to patients or participants, with push notifications to schedule them per user. Integrated Development Environment This component is optional. This component allows authorized developers and data scientists to build, test, and deploy algorithms that work with the LAMP Platform in a secure manner. This component may be deployed multiple times to support different development needs or users. We additionally recommend JupyterLab for Python data analysis, RStudio for R data analysis, and Visual Studio Code for TypeScript development. Integrating development and data analysis with the LAMP Platform deployment increases data throughput and security, but access to these instances should be guarded carefully to avoid data leaks. When: If your organization would like to create customized user experiences for your clients or clinicians. Prerequisites: Your organization will need to provision a content delivery system to serve the user interface. Options: You can use the existing mindLAMP App UI designed by the Division of Digital Psychiatry with your customized Native App or Backend. Native App Smartphone (iOS, Android) This component is used to collect high precision sensor measurements from the numerous sensors outlined in the LAMP API documentation. By embedding a miniature version of the LAMP server and database, it supports active bi-directional synchronization between two devices (i.e. watch and phone, or phone and cloud). By embedding the App UI, patients and participants can interact with clinic or study-scheduled survey instruments and cognitive assessments to record active data and metadata. Wearable (Apple Watch, Google wearOS) This component is used to collect high precision sensor measurements from the numerous sensors outlined in the LAMP API documentation. By embedding a miniature version of the LAMP server and database, it supports active bi-directional synchronization between two devices (i.e. watch and phone, or phone and cloud). When: if your organization would like to include support for additional sensor instruments, such as third party medical devices. Prerequisites: Your organization will need to purchase membership with Apple and/or Google's developer program, submit modifications to the app for App Store review, and dedicate personnel to maintenance and updates. Options: You can use the existing mindLAMP Native App submitted by the Division of Digital Psychiatry and vetted by Apple and Google with your customized Frontend or Backend. It is always possible to customize the activities and sensors your patients will see in the app using the standard frontend hosted by BIDMC. You do not need to self-host the frontend. Even if your organization chooses to make modifications to any of these components when self-deploying them, they remain compatible with one-another. For example, if one organization self-deploys a new Frontend user experience or adds medical devices support to the Native App, it remains compatible with another organization's self-deployed Backend. Edit this page Last updated on Nov 19, 2024 by Juan Previous Modifying the frequency of a sensor's data collection Next Deployment Recommendations","s":"Prerequisites for Deploying the LAMP Platform","u":"/deploy/prereqs","h":"","p":625},{"i":628,"t":"Deploying LAMP Provisioning the LAMP Platform On this page Provisioning the LAMP Platform BIDMC Digital Psychiatry's LAMP Platform The LAMP Platform is cloud-agnostic and can be hosted on Amazon Web Services, Microsoft Azure, Google Cloud, any other cloud provider, or self-hosted on-prem. The LAMP Platform requires computing and storage resources (i.e. AWS EC2 and EBS), along with external network access; managed services from cloud providers tend to provide robust and maintenance-free bring-up for the LAMP Platform and are recommended over self-hosting on-prem. Furthermore, additional services such as Amazon CloudFront or CloudFlare allow less expensive and more effective caching and edge content delivery of the mindLAMP Dashboard and UI without the need for multi-region deployments. A single Docker Stack file (docker-compose.yml) is used to automate single-node or multi-node deployments, and requires Docker Swarm (multi-node for cloud testing, integration, and production usage, or single-node for local testing or smaller deployments). Though possible to use Kubernetes or Terraform to manage larger scale deployments, the LAMP Platform has only been tested with Docker Swarm. We provide additional examples for (1) local development, and (2) Amazon Web Services. If you or your organization have further questions about choosing a cloud provider or deploying on-prem, please contact us. Segmenting Compute Resources​ BIDMC Digital Psychiatry's LAMP Platform When developing or testing the LAMP Platform, it is useful and effective to segment compute resources and develop natively in the cloud (or on-prem). Consider carefully how your organization expects to the use the LAMP Platform and segregate computing resources (nodes) to reduce cost and improve performance. The LAMP Platform source code repositories are hosted on GitHub and use the GitHub Actions and GitHub Packages features to quickly perform continuous testing, integration, and deployment. As code is pull requested from a feature branch into the master branch, it should pass a round of code review and pass any/all unit tests. Once the code is merged, the automated CI/CD will prepare and upload Docker images. We highly recommend the use of Portainer to remotely manage your Docker Swarm nodes and container health, as well as Traefik for managing service mesh routing and in-flight TLS encryption; additional Docker Stack files and instructions are provided for both. The Traefik router interfaces with Docker Swarm and your DNS provider to automatically manage internal and external access to services, according to the configuration in the Docker Stack files provided. To monitor node health and container resource metrics, we recommend Netdata and have included it in the stack file below. If you'd like to follow along but would like to test the deployment out first, or don't have provisioned resources yet, consider using Play With Docker, a free service from the Docker team where you can provision a temporary Swarm cluster. Edit this page Last updated on Nov 19, 2024 by Juan Previous Costs of Deploying the LAMP Platform Next Preparing Resources on AWS Segmenting Compute Resources","s":"Provisioning the LAMP Platform","u":"/deploy/provisioning","h":"","p":627},{"i":630,"t":"Deploying LAMP Deployment Recommendations On this page Deployment Recommendations Disclosure We encourage all self-deploying users to consult the legal and IT departments, as well as sign a Business Associate Agreement (BAA) with the cloud provider to comply with HIPAA regulations. LAMP is completely free, open source software; as a result you are free to follow any or all steps that are suggested. However, we can only assure a successful deployment of the LAMP Platform if each required step is followed. If these steps are not implemented correctly, we are unable to guarantee LAMP will deploy properly. We are also unable to offer the technical support from our team for other deployments. Technical Requirements The use of Docker is imperative to successful self-deployment. A single Docker Stack file is used to automate single-node or multi-node deployments, and requires Docker Swarm (multi-node for cloud testing, integration, and production usage, or single-node for local testing or smaller deployments). The LAMP Platform has only been tested with Docker Swarm, so therefore our team is only equipped to provide support for those using Docker or Docker compatible services. We highly recommend the use of Portainer as a Swarm Management Console to make it easier to troubleshoot failed deployments, rapidly test and integrate new components, and effectively monitor container logs and health. Read this documentation to learn more about Portainer and how to configure and use it. We also recommend Traefik for managing service mesh routing and in-flight TLS encryption; additional Docker Stack files and instructions are provided for both in the self-deploy documentation. Remote Access (WAF) Notes​ The mobile apps and browsers must make an initial connection to the hosted VersionCheck API (part of the App Gateway) before downloading the user interface component. If your organization chooses to submit separate copies of the mobile apps to the Apple/Google app stores, you will also be responsible for deploying the App Gateway within your organization as well. This also means your organization must \"pin\" the versions of components as accessed from the VersionCheck API. If your organization is NOT deploying an internal App Gateway (i.e if using the existing mindLAMP apps on the App Store) then you will be using the App Gateway as hosted by the Division of Digital Psychiatry. (This must be disclosed in security/IT diagrams.) Edit this page Last updated on Nov 19, 2024 by Juan Previous Prerequisites for Deploying the LAMP Platform Next Costs of Deploying the LAMP Platform Remote Access (WAF) Notes","s":"Deployment Recommendations","u":"/deploy/recs","h":"","p":629},{"i":632,"t":"Deploying LAMP Configuring your server to add Sensors and Activities On this page Configuring your server to add Sensors and Activities By default, you will not be able to assign any activities or sensors to your participants (or groups of participants). At first, when you try to add activities and sensors in the dashboard, none are available in the dropdown. This is because not every mindLAMP deployment needs all of the sensors or activities that are available. Instead, you must individually enable each sensor or activity type you will need. This process is called \"adding an ActivitySpec\" or \"adding a SensorSpec\". Steps to add a SensorSpec (or ActivitySpec): Navigate to https://docs.lamp.digital/api/create-a-sensor-spec (https://docs.lamp.digital/api/create-an-activity-spec) Click the \"authorize\" button in the top right corner Enter your server's address, your server's admin username, and your server's admin password Figure out the SensorSpec name (or ActivitySpec) of the sensor (activity) you would like to enable. To see a full list of SensorSpec names, check here: https://docs.lamp.digital/data_science/data_types/sensor_types. To see a full list of ActivitySpec names, check here: https://docs.lamp.digital/data_science/data_types/activity_types. For example, you will see that the SensorSpec for the accelerometer sensor is called \"lamp.accelerometer\". Scroll down to the \"Body\" text box. Replace the field with {\"name\":}. For example, to add the \"accelerometer\" sensor, use: {\"name\":\"lamp.accelerometer\"} Scroll down to the text box that says \"api.lamp.digital\". Replace this text with your server's address. Select \"execute\". Check back in the dashboard for an updated dropdown list! Automated Script​ import LAMP ACTIVITY_SPEC_LIST = [ \"lamp.spatial_span\", \"lamp.cats_and_dogs\", \"lamp.jewels_a\", \"lamp.jewels_b\", \"lamp.dbt_diary_card\", \"lamp.balloon_risk\", \"lamp.pop_the_bubbles\", \"lamp.journal\", \"lamp.breathe\", \"lamp.recording\", \"lamp.survey\", \"lamp.scratch_image\", \"lamp.tips\", \"lamp.goals\", \"lamp.medications\", \"lamp.memory_game\", \"lamp.spin_wheel\", \"lamp.maze_game\", \"lamp.emotion_recognition\", \"lamp.symbol_digit_substitution\" ] SENSOR_SPEC_LIST = [ \"lamp.accelerometer\", \"lamp.accelerometer.motion\", \"lamp.analytics\", \"lamp.blood_pressure\", \"lamp.bluetooth\", \"lamp.calls\", \"lamp.device_state\", \"lamp.distance\", \"lamp.flights\", \"lamp.gps\", \"lamp.gps.contextual\", \"lamp.gyroscope\", \"lamp.heart_rate\", \"lamp.height\", \"lamp.magnetometer\", \"lamp.respiratory_rate\", \"lamp.segment\", \"lamp.sleep\", \"lamp.sms\", \"lamp.steps\", \"lamp.weight\", \"lamp.wifi\", ] print(\"[LAMP Platform] ActivitySpec & SensorSpec Initialization Tool\") print(\"You must enter your username, password, and server address to continue installation.\") print(\"Username: admin [CANNOT BE CHANGED]\") LAMP.connect(\"admin\", input(\"Password: \"), input(\"Server Address: \")) for spec in ACTIVITY_SPEC_LIST: print(f\"Creating ActivitySpec '{spec}'...\") LAMP.ActivitySpec.create({ \"name\": spec }) for spec in SENSOR_SPEC_LIST: print(f\"Creating SensorSpec '{spec}'...\") LAMP.SensorSpec.create({ \"name\": spec }) Edit this page Last updated on Nov 19, 2024 by Juan Previous Configure OAuth for Google Next Components of the LAMP Platform Automated Script","s":"Configuring your server to add Sensors and Activities","u":"/deploy/enabling_sensors_and_activities","h":"","p":631},{"i":634,"t":"Deploying LAMP Testing the LAMP Platform On this page Testing the LAMP Platform Once you've deployed the LAMP-server and LAMP-database, you'll be able to use the mindLAMP app (either on your mobile device or in a desktop browser) to connect to your instance. All data is encrypted before communication between your browser or the app to and from your newly deployed server. No data will be communicated with any other server, including the default API server at api.lamp.digital or other third party services. Verify the status of the database. curl -k https://admin:DB_PASSSWORD_HERE@db.example.com/ or mongo 'mongodb://username:password@databaselocation:port/databasename' If the mongo command cannot be found, you can also try mongosh Verify the status of the LAMP Platform API Server. curl -k https://api.example.com/ Check the Docker service logs for LAMP_server to locate your generated server administrator password. docker service logs LAMP_server caution The logs will only print the administrator password once. Restarting the service will not reveal the password again. If you did not save the password when you initialized the database, you can find the password by decrypting the secret key found in the credential collection using your root key. See the decryption script below this page. Verify that the newly generated password (GENERATED_PASSWORD_HERE) works. curl -k https://api.example.com/researcher -H 'Authorization: Basic admin:GENERATED_PASSWORD_HERE' Create a Researcher and a Participant using the browser management user interface to verify the setup works as expected. To jumpstart your instance of the LAMP Platform and test surveys or other activities, follow the instructions in Create Surveys and import the file below into the Researcher you just created. [lamp_example_survey_battery_export.json](Testing the LAMP Platform/export.json) If any of the above steps fails to complete successfully you will not be able to reach this step. Password encrypt/decryption script​ If you need to manually encrypt/decrypt your secret key, see the below script. You can execute this script via terminal with node . Please replace with the root key used in your lamp-server service. #!/usr/bin/env node const PRIVATE_KEY = // DO NOT SHARE! const crypto = require('crypto') const mode = (process.argv[2] || '') const input = (process.argv[3] || '') let output = 'Usage: passcrypt.js ' try { if (mode === 'encrypt') { let ivl = crypto.randomBytes(16) let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(PRIVATE_KEY, 'hex'), ivl) output = Buffer.concat([ ivl, cipher.update(Buffer.from(input, 'utf16le')), cipher.final() ]).toString('base64') } else if (mode === 'decrypt') { let dat = Buffer.from(input, 'base64') let cipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(PRIVATE_KEY, 'hex'), dat.slice(0, 16)) output = Buffer.concat([ cipher.update(dat.slice(16)), cipher.final() ]).toString('utf16le') } console.dir(output) } catch(e) { console.log('*** ERROR: Could not ' + mode + ' the string. ***') process.exit(1) } Edit this page Last updated on Nov 19, 2024 by Juan Previous Deploying the LAMP Platform Next Troubleshooting Deployment Password encrypt/decryption script","s":"Testing the LAMP Platform","u":"/deploy/testing","h":"","p":633},{"i":636,"t":"Deploying LAMP Deploying the LAMP Platform On this page Deploying the LAMP Platform caution Although some steps are able to completed using other methods, please follow these instructions as closely as possible. Deviation from these deployment recommendations means BIDMC staff cannot provide technical support. You must have a configured Docker Swarm cluster to continue. Please follow all steps below in the exact order specified, though you may skip optional steps. The files provided below support these orchestration tools: Docker Compose (single-node) Docker Swarm (single-node or multi-node) WARNING: If creating a multi-node deployment, follow the proper procedures for manager/worker node allocation. An N manager cluster tolerates the loss of at most (N-1)/2 managers. If creating a 2-node cluster and both are designated as managers, CATASTROPHIC FAILURE AND SEVERE DATA LOSS may occur if EITHER node loses connectivity for more than 5 minutes. Kubernetes (multi-node) For more information on using Kubernetes, follow this guide or this guide instead. Prerequisites​ This step is required. Configure firewall rules as needed to avoid directly opening ports on your nodes, and instead appropriately route traffic through ports 80 (HTTP) and 443 (HTTPS). Create a new network called public to connect all externally accessible services. docker network create --driver overlay --attachable public Using your DNS provider of choice, provision a domain name (here we use [example.com](http://example.com) to represent your domain name and 1.1.1.1 to represent your node's IP address). DNS Records ┌───────────────┬──────┬─────────┬──────┐ │ RECORD NAME │ TYPE │ VALUE │ TTL │ ├───────────────┼──────┼─────────┼──────┤ │ example.com │ A │ 1.1.1.1 │ 3600 │ │ *.example.com │ A │ 1.1.1.1 │ 3600 │ └───────────────┴──────┴─────────┴──────┘ If you have multiple nodes in your cluster, be sure to configure alternate IP address values for all DNS records. DNS Records For example, on AWS Route53, ROUND-ROBIN refers to Multivalue Answer response types without health-check enabled. ┌───────────────┬──────┬─────────┬──────┬─────────────┬─────────┐ │ RECORD NAME │ TYPE │ VALUE │ TTL │ MODE │ ALIAS │ ├───────────────┼──────┼─────────┼──────┼─────────────┼─────────┤ │ example.com │ A │ 1.1.1.1 │ 3600 │ ROUND-ROBIN │ node-01 │ │ example.com │ A │ 2.2.2.2 │ 3600 │ ROUND-ROBIN │ node-02 │ │ *.example.com │ A │ 1.1.1.1 │ 3600 │ ROUND-ROBIN │ node-01 │ │ *.example.com │ A │ 2.2.2.2 │ 3600 │ ROUND-ROBIN │ node-02 │ └───────────────┴──────┴─────────┴──────┴─────────────┴─────────┘ Cloud Mesh Router​ This step is optional and can be skipped. We recommend deploying Traefik as a Cloud Mesh Router to make it easier to connect services and components, generate SSL certificates for encrypting traffic, diagnose traffic issues, and capture access logs for auditing. Docker Stack: **traefik.yml** You MUST replace the following configuration variables in your copy of this file: administrator@example.com version: \"3.7\" services: traefik: image: traefik:latest command: - \"--log.level=INFO\" - \"--accesslog=true\" - \"--api=true\" - \"--providers.docker=true\" - \"--providers.docker.swarmMode=true\" - \"--providers.docker.exposedByDefault=false\" - \"--entrypoints.web.address=:80\" - \"--entrypoints.websecure.address=:443\" - \"--entrypoints.websecure.http.tls.certResolver=default\" - \"--entrypoints.web.http.redirections.entryPoint.to=websecure\" - \"--entrypoints.web.http.redirections.entryPoint.scheme=https\" - \"--entrypoints.web.http.redirections.entryPoint.permanent=true\" - \"--certificatesResolvers.default.acme.email=administrator@example.com\" - \"--certificatesResolvers.default.acme.storage=/data/acme.json\" - \"--certificatesResolvers.default.acme.tlsChallenge=true\" volumes: - \"/var/run/docker.sock:/var/run/docker.sock:ro\" - \"traefik-ssl:/data/\" ports: - target: 80 protocol: tcp published: 80 mode: ingress - target: 443 protocol: tcp published: 443 mode: ingress networks: - public deploy: mode: replicated placement: constraints: - node.role == manager networks: public: external: true volumes: traefik-ssl: docker stack deploy --compose-file traefik.yml router We recommend deploying [Portainer](https://www.portainer.io/) as a Swarm Management Console to make it easier to troubleshoot failed deployments, rapidly test and integrate new components, and effectively monitor container logs and health. Read this documentation to learn more about Portainer and how to configure and use it. LAMP Platform​ This step is required. Docker Stack: **lamp.yml** You MUST replace the following configuration variables in your copy of this file: ROOT_ENCRYPTION_KEY_HERE: A random 32-bit hexadecimal string. See below DB_PASSSWORD_HERE: An random 8-bit hexadecimal string. See below YOUR_PUSH_KEY_HERE → Please contact us to enable push notifications. (optional) api.example.com Your LAMP Platform API Server domain shared with others to use. The first two passwords must be two cryptographically secure hexadecimal strings. Below are commands you can run to generate these two strings. openssl rand -hex 8 # DB_PASSWORD_HERE openssl rand -hex 32 # ROOT_ENCRYPTION_KEY_HERE After generating these strings and obtaining your LAMP Platform API server domain, substitute them into the following YAML file and deploy the file. version: '3.7' services: server: image: ghcr.io/bidmcdigitalpsychiatry/lamp-server:2023 healthcheck: test: wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1 environment: HTTPS: 'off' ROOT_KEY: 'ROOT_ENCRYPTION_KEY_HERE' DB: 'mongodb://admin:DB_PASSSWORD_HERE@database:27017/' PUSH_API_GATEWAY: 'https://app-gateway.lamp.digital/' PUSH_API_KEY: 'YOUR_PUSH_KEY_HERE' DASHBOARD_URL: 'dashboard.lamp.digital' REDIS_HOST: 'redis://cache:6379/0' NATS_SERVER: 'message_queue:4222' networks: - default - public logging: options: max-size: \"10m\" max-file: \"3\" deploy: mode: replicated update_config: order: start-first failure_action: rollback labels: traefik.enable: 'true' traefik.docker.network: 'public' traefik.http.routers.lamp_server.entryPoints: 'websecure' traefik.http.routers.lamp_server.rule: 'Host(`api.example.com`)' traefik.http.routers.lamp_server.tls.certresolver: 'default' traefik.http.services.lamp_server.loadbalancer.server.port: 3000 placement: constraints: - node.role == manager database: image: mongo:6.0.4 environment: MONGO_INITDB_ROOT_USERNAME: 'admin' MONGO_INITDB_ROOT_PASSWORD: 'DB_PASSWORD_HERE' volumes: - mongo_data:/data/db networks: - public deploy: mode: replicated update_config: order: stop-first failure_action: rollback placement: constraints: - node.role == manager cache: image: redis:6.0.8-alpine healthcheck: test: redis-cli ping deploy: mode: replicated update_config: order: stop-first failure_action: rollback placement: constraints: - node.role == manager message_queue: image: nats:2.1.9-alpine3.12 healthcheck: test: wget --no-verbose --tries=1 --spider http://localhost:8222/varz || exit 1 deploy: mode: replicated update_config: order: start-first failure_action: rollback placement: constraints: - node.role == manager volumes: mongo_data: networks: public: external: true Note: If you are deploying more than one stack, please be sure that all traefik variables (for example, traefik.http.routers.lamp_dashboard.rule) under \"labels\" are unique. Otherwise, this will cause issues with both the deployment of this container and the other containers that contain the duplicate variables. If you've deployed the Swarm Management Console, log into your swarm cluster and navigate to the Stack tab on the left sidebar. Paste the contents of the stack file into the editor pane and tap \"Deploy\", instead of running the command below. docker stack deploy --compose-file lamp.yml lamp Maintaining and Updating the LAMP Platform​ If you are using this Docker Stack provided, you will only need to run a docker service update command on the API Server to pull the latest image. Because Docker image versioning is calendar-based, at the moment you will manually need to update from 2022 to 2023, and so on. If you are deploying multiple LAMP stacks, please ensure the traefik router rules have been renamed! (i.e. Ensure traefik.http.routers.lamp_dashboard.rule and traefik.http.routers.lamp_dashboard_2.rule are distinct.) If two or more instances of the same rule exist, the router will overwrite the first instance. Edit this page Last updated on Nov 19, 2024 by Juan Previous Deploying via CloudFormation Next Testing the LAMP Platform Prerequisites Cloud Mesh Router LAMP Platform Maintaining and Updating the LAMP Platform","s":"Deploying the LAMP Platform","u":"/deploy/deploying","h":"","p":635},{"i":638,"t":"Developing LAMP Just-In-Time Adaptive Interventions On this page Just-In-Time Adaptive Interventions This is a proof-of-concept for the LAMP Automations system. The workflow is detailed below: Patient logs into mobile app (iOS/Android) Mobile app uses Study configuration to activate device sensor data collection (i.e. which sensors, frequency per sensor, misc. settings) Mobile app collects sensor data in background and caches it Conditions must be met: device charged/charging + active WiFi connection Mobile app bulk uploads cached sensor data to specified server (organization) Mobile app individually uploads activity data upon participant’s completion of a session API Server processes and stores this data into database API Server signals all listeners that new data has arrived (per-study, per-activity, per-participant) Automations worker receives new data notification Worker searches its installed scripts catalog for scripts that specify a matching trigger condition For example, the BIDMC College Study has installed their own script (source code provided here). Worker executes scripts, providing the new data notification information to the script Scripts (third-party user-specified code) are executed in isolated docker containers Script processes the data as it needs and may optionally execute actions Example: BIDMC college study script Script computes change in daily survey score today vs. yesterday += 3 points If condition is met, script selects a random activity (meditation, journaling, placebo) to send to participant Script sends message containing activity ID to API server for mobile app push notification Participant receives push notification on their mobile device Participant opens push notification and starts activity session Upon completion of session (i.e. saved a journal entry), activity data is uploaded to server Repeat this feedback cycle from step #6 Private Sensors and Tags​ lamp.gps.contextual Sensor: This was a mindLAMP 1 feature that collected street-level GPS (not lat/long coordinates) with a paired survey asking about social and environmental context (who you were with and where you were) between 5-30 min of taking a survey in the app. lamp.demographics Tag: This holds processed clinical scale data from when a patient is onboarded onto a study (i.e. via paper-pencil surveys or RedCap, etc.) beiwe.* Sensors: The full list of these Sensors is below; these are migrated sensors from when the Beiwe app was used alongside mindLAMP 1. beiwe.identifiers beiwe.accelerometer beiwe.bluetooth beiwe.calls beiwe.gps beiwe.power_state beiwe.texts beiwe.wifi beiwe.audio_recordings beiwe.survey_answers beiwe.survey_timings beiwe.app_log beiwe.ios_log lamp.dashboard.activity_details and lamp.dashboard.survey_description Tags: These were placeholder tags for the mindLAMP v1 to v2 migration; the Activity API was not fixed at the time and did not support activity icons, descriptions, etc. and so these Tags were required on each customized Activity. lamp.dashboard.credential_roles Tag: The Care Team feature allowed attaching a separate Tag with a dictionary, where each key matched a Credential set on the Participant; the values for each key (the Credential's email address) was a name, photo, and description of the individual's role in the care team. This is no longer supported as a feature. lamp.name Tag: This added backwards-compatible support for the Participant.aliases feature. lamp.messaging Tag: This added backwards-compatible support for the Conversations feature of the dashboard. lamp.dashboard.welcome_dismissed Tag: Unknown; this Tag was never used. lamp.selectedStudies, lamp.selectedActivities, and lamp.selectedSensors Tags: Due to bugs in the earliest version of the mindLAMP v2 dashboard, these tags held an array of studies, activities, or sensors that were selected by the currently logged in Researcher. This is now defunct and should not be used (localStorage should be used instead). Edit this page Last updated on Nov 19, 2024 by Juan Previous Building New Activities Next App Gateway Private Sensors and Tags","s":"Just-In-Time Adaptive Interventions","u":"/develop/adaptive_interventions","h":"","p":637},{"i":640,"t":"Deploying LAMP Troubleshooting Deployment On this page Troubleshooting Deployment This page contains fixes for potential issues you may encounter when using LAMP. However, it is not comprehensive. If you encounter an issue you are unable to resolve with the help of this page, please help us improve by posting your issue at community.lamp.digital Large Logs​ LAMP-server is designed for long uptimes and detailed logging. An unfortunate side-effect of this is that, especially over a long period of time, logging files can grow large and affect available disk space, negatively impacting docker performance. Check your disk space usage in the terminal of your lamp-server node with: df If it is 100%, navigate to your docker directory (try cd /var/lib/docker) and run du -h --max-depth=1 containers/ This command will list your containers space usage. If LAMP-server is very large (in excess of 10gb), you can attempt to clean the logs by running docker stop YOUR_SERVER_ONTAINER_ID_HERE && docker rm YOUR_CONTAINER_ID_HERE This will stop and remove your container, at which point docker swarm should spin up a new one. To prevent this issue from happening in the future, add the following to your docker compose file. The docs YAML file has this added as of September 2nd, so this bug should not occur if you began using LAMP after this date. logging: options: max-size: \"10m\" max-file: \"3\" Edit this page Last updated on Nov 19, 2024 by Juan Previous Testing the LAMP Platform Next Complex Password Requirements Large Logs","s":"Troubleshooting Deployment","u":"/deploy/troubleshooting","h":"","p":639},{"i":642,"t":"Developing LAMP Building New Activities On this page Building New Activities Because the LAMP Platform is built around around a simple native core and a flexible WebView UI, any HTML/CSS/JavaScript code that works in a browser can work in the app. Learning modules, surveys, cognitive tests, and interventions all use the same API and using a framework such as React makes it simple, for example, to create new interventions as needed with patient/participant feedback. Any Javascript-based code can be added the LAMP Platform using the ActivitySpec API, as long as it uses window.postMessage() and window.addEventListener() API to receive the Activity settings and submit the ActivityEvent once complete. Approximately ~40 lines of JavaScript + React code, shown on the left produces a naïve implementation of the Jewels game, shown on the right. info If you'd like to try creating your own, but don't have a ReactJS development environment, consider using CodeSandbox, a free service. Specific Instructions to add Custom Activity To add a custom activity, the HTML page must be compressed in base64 and must be able to be accessed by the dashboard. To do this, you can run this command on your html file: $ cat index.html | base64 > index.html.b64 In your Activity Spec DB document it should have an executable and a settings attribute. Should look something similiar to this: \"executable\": \"https://path/to/your/index.html.b64\" \"settings\": { \"type\": \"object\", \"properties\": { \"settings\": { \"title\": \"Activity Settings\", \"type\": \"object\", \"required\": [ \"totalTrials\", \"maxTime\" ], \"properties\": { \"totalTrials\": { \"title\": \"Total Trials\", \"description\": \"The number of trials.\", \"type\": \"number\", \"default\": 20, \"minimum\": 1, \"maximum\": 100, \"ui:grid\": { \"xs\": 4 } }, \"maxTime\": { \"title\": \"Max Time\", \"description\": \"The time it takes to get to the stopsign in seconds\", \"type\": \"number\", \"default\": 0.75, \"minimum\": 0.1, \"maximum\": 2, \"ui:grid\": { \"xs\": 4 } } } } } }, Custom Activity HTML file Back Button Function in Activity​ In your HTML document, include a function where the user can revert back to LAMP. The onclick attribute should then call a parent postMessage. Something like this: function clickedBackButton(){ console.log('clicked back button') parent.postMessage(null, '*'); } In that specific example, the postMessage is sent to the LAMP with no data. Initialized Settings from LAMP​ Using the settings we added to the document, we can access these variables using the addEventListener() window.addEventListener(\"message\", (event) => { // console.log(event) settings = event.data.activity.settings totalTrials = settings.totalTrials // the totalTrials settings can be accessed here totalTrials = 20 //default maxTime = settings.maxTime // the maxTime settings can be accessed here }, false); Edit this page Last updated on Nov 19, 2024 by Juan Previous Continuous Monitoring & Intervention Delivery Next Just-In-Time Adaptive Interventions Back Button Function in Activity Initialized Settings from LAMP","s":"Building New Activities","u":"/develop/build_new_activities","h":"","p":641},{"i":644,"t":"Developing LAMP App Gateway On this page App Gateway note This documentation is for BIDMC Digital Psychiatry internal use only. Introduction​ The mindLAMP apps for both iOS and Android enable two additional features beyond what is offered by simply logging into the dashboard and bookmarking the tab on the user's mobile device: sensor data collection, and push notification scheduling for Activities. However, sending a push notification from a LAMP server to a mobile device requires encrypted communication with official Apple and Google gateway servers (called Apple Push Notification Service, or APNS, and Google Firebase Cloud Messaging, or FCM). These gateways are only authorized to receive push notification requests from servers with an approved developer certificate (a file with the extention .p8 or .p12) and developers must be granted access to this feature. Apple and Google both require BIDMC Digital Psychiatry to maintain records of approved IRB documents or clinical protocols (if not a research study) to allow external collaborators' LAMP servers to communicate with the native iOS and Android apps. This is because both apps are published under John Torous's developer accounts. Notification Flow​ As a result, the LAMP Platform includes an App Gateway component (located at app-gateway.lamp.digital) that acts as an intermediary: A patient logs in to the mindLAMP iOS app on a collaborator's LAMP server. The collaborator's LAMP server schedules push notifications to be sent to the new iOS device registered. At time of notification, the collaborator's LAMP server sends the notification to the App Gateway hosted by BIDMC. This notification request contains the collaborator's unique API Key. These API Keys should NEVER be shared with others. The App Gateway verifies the included notification's API Key but does NOT have access to the notification contents, to ensure privacy. If the API Key is valid, the App Gateway forwards the notification request to either Apple or Google servers automatically. If the API Key is NOT valid, an error message is returned to the collaborator's LAMP server. Supported Features​ This App Gateway component MUST NOT be self-hosted by external collaborators, unless they also intend to self-publish the iOS and Android apps as well (which is highly discouraged). The App Gateway supports multiple destinations, and each has a unique device_token prefix: Apple Push Notification Service (iOS/macOS devices; apns:) Google Firebase Cloud Messaging (Android devices; gcm:) Amazon Web Services Simple Email Service (Email; mailto:) Amazon Web Services Simple Notification Service (SMS; sms:) Slack Webhooks (Slack channels; slack:) External collaborators are NOT PERMITTED to use mailto:, sms:, or slack: destinations. More information on sending messages through the App Gateway from the command line can be found here. Generating API Keys​ To allow external collaborators to send push notifications to users' iOS and Android devices, the following steps must be completed: collaborator organization must complete the consortium enrollment form collaborator organization must make the request for an API Key on the community forum (emailed requests ARE NOT PERMITTED) a BIDMC team member must save this information to the Projects → LAMP Platform → Documents → People Pipeline → Consortium Members database in the internal team Notion. the BIDMC team member must generate a new API Key in the terminal using this command: openssl rand -base64 12 An API Key is actually just a randomly generated string to uniquely identify an external collaborator, and contains no other information. Should an API Key need to be replaced, a new one can be generated and replaced in this database (but all previously generated keys must be recorded in the Notes field). the BIDMC team member must add this API Key to the App Gateway service in the internal Docker console (located at console.lamp.digital). Once logged in, locate mindLAMP → Stacks → LAMP → Editor (tab) and scroll down to find app-gateway. Edit this YAML configuration under environment → API_KEYS: add the new API Key at the end of this list, separated by a comma. (DO NOT include a trailing comma.) Press the Update the Stack button. the BIDMC team member should respond to the collaborator organization via private DM on the forum with this new API Key. the collaborator organization fills in the API Key in their LAMP Platform configuration (see here for more info) info Should an API Key be revoked, follow the above procedures to remove the API Key from the Docker console and notify the external collaborator organization. API Usage​ The utility functions provided by Cortex should be preferred over making raw API calls to the App Gateway. However, an example of the raw API call using cURL is provided below. curl -XPOST \"https://app-gateway.lamp.digital/push\" \\ -H 'Content-Type: application/json' \\ --data-binary @- <<'EOF' { \"api_key\": \"YOUR_API_TOKEN_HERE\", \"device_token\": \"apns:YOUR_APNS_DEVICE_TOKEN_HERE\", \"payload\": { \"aps\": { \"alert\": \"Hello world!\", \"badge\": 0, \"sound\": \"default\", \"mutable-content\": 1, \"content-available\": 1 }, \"notificationId\": \"test123\", \"expiry\": 84600000, \"actions\": [] } } EOF Internal Flow​ The flow of data is shown below: The Automations Worker component handles all push notification scheduling working in tandem with the API Server using the LAMP-js SDK. It caches CRON expressions matching to Activity IDs and Participant IDs for delivery. The workflow is shown below: Edit this page Last updated on Nov 19, 2024 by Juan Previous Just-In-Time Adaptive Interventions Next Scheduling Tasks with Cron Jobs in LAMP Introduction Notification Flow Supported Features Generating API Keys API Usage Internal Flow","s":"App Gateway","u":"/develop/app_gateway","h":"","p":643},{"i":646,"t":"Developing LAMP How the Platform Works On this page How the Platform Works The LAMP Platform always collects data in a secure way before automatically processing and harmonizing it for you. Researchers/clinicians, and patients/participants can view their data in the frontend user interface. Patients will always retain ownership when contributing their data to your study or clinic and may always download and view their own data. Cognitive tests and survey instruments collect high quality metadata that can measure attention, focus, memory performance, and more. The LAMP Protocol, upon which the LAMP Platform is built, may also be integrated into other systems as it is intuitive, simple, and has security and privacy built-in. It models active and passive data together as evolving streams of events, and data becomes reactive and clinically actionable through user-defined applets across R, Python, and JS. Credential management is built into the object hierarchy, which uses OpenAPI and JSONSchema to mark up extensible interfaces. The industry encryption standards AES-256 and TLSv1.3 facilitate secure storage and transmission of data in a HIPAA, COPPA, and GDPR-compliant manner. The LAMP Platform consists of two broad domains: (1) local: the components that users will see and interact with through smartphone or wearable devices, and (2) remote: the components located off-device that process data, coordinate applets, and handle synchronization. The app serves to both capture diverse streams of sensor and activity measurements ranging from heart rate to mood and to prompt suggested user interactions. It informs the LAMP Platform with a micro-temporal slice of the user’s physical and mental health. The server components supporting the LAMP Platform play an equally important role in securely encrypting and processing the data, establishing the user’s “digital fingerprint” and predicting changes that could potentially result in relapse. app-based interventions can be deployed to improve the user’s health and relevant health data can automatically be shared with authorized care team members. The figures below detail one operation typically performed by the LAMP Platform. Shown on the left-hand side is the app, and on the right-hand side is the server. Note that both pieces consist of numerous components that work together as a modular distributed system to transfer and process data in a clinically relevant context. A full specification of all components and their interactivity is documented in later sections. Please note that an important distinction in naming is made between the local and remote domains: the components of the former are prefixed with “mindLAMP” where the components of the latter are prefixed only with “LAMP” as this distinction clarifies the scope and requirements of the components themselves. Step 1: Sensor events are recorded in real-time.​ High-frequency sensors on the mobile or wearable device record measurements based on the user’s current configuration settings defined by an administrator. This data is stored in a buffer on the device's hardware managed by the operating system (either iOS or Android) and provided to the app periodically while it is in the background. Step 2: Collected events are cached, awaiting server reachability.​ The device’s buffer and operating system make no guarantees to save data from the current moment for the next time the app is run in the background. Because of this and the likelihood that the remote server may not be reachable due to poor signal, the measurements are immediately cached by the app whenever it is notified in the background. When battery levels are sufficient, and network connectivity to the remote server available, and enough data is cached, the app begins synchronization. Step 3: Server receives and processes requests from the app.​ The app submits a request to the server for synchronizing and uploading its cached data. Once uploaded successfully, it is unpacked and examined by the server for further automated processing. Step 4: Server coordinates internal components for processing.​ The server prepares instructions for internal components based on the data uploaded by the app. These instructions are pushed through the internal data bus (a message queue) that connects all internal controllers in the platform. The extensibility of the internal components and the data bus interconnecting them means components can be swapped out or replaced depending on context. In deployments or regions where some features should be disabled, their relevant components are \"unplugged\" from this data bus. Step 5: Database records the incoming data.​ Depending on the server’s system configuration and the content of the data uploaded, the database then records all event data and schedules an automated backup. The database considers the origin of the events as it saves them, harmonizing data from various sensors through a unified schema. ![](assets/Untitled 75.png) Step 6: The scheduler coordinates and runs automations.​ Once the database completes saving data and any backup processes, the scheduler component is engaged to determine if any data processing “applets” or other internal maintenance tasks need to run. After assessing cost and priority, the scheduler creates an execution plan consisting of the above and notifies these components. The scheduler relies on heuristics gathered from audit logs to determine the plan. Step 7: Applets are launched into a safe environment and run.​ Assuming no internal maintenance tasks need to run, the scheduler may create an execution plan with only a single applet. Once started, a new virtual environment is prepared and securely isolated from other data. For example, an R environment would analyze the script to run and install the correct versions of all required packages, replicating the environment used by the applet's author. Please contact us directly for guidance on delivery of just-in-time interventions. Step 8: Applet results are saved after being run.​ As the applet executes, its input and output are spliced from the automation controller and saved as tags. For example, an applet called \"com.test.some_script\" may create a new tag “com.test.some_script” attached to some resource in the database, or append to an existing tag with the same name. Any runtime logs are extracted separately from this result. Step 9: Applet results are persisted for later access.​ If an applet is configured to persist its output, the data are persisted to the database as a tag and may be accessed by a client app directly at a later time. For example, an applet may compute a dynamic visualization to be cached, or it could lookup login credentials from a predefined tag to access and convert data from a third-party system such as Fitbit into native resource objects which are then persisted by the database. Step 10: Scheduler updates invocation and audit log.​ Once an execution plan completes, the scheduler records statistics about it for its next engagement. Step 11: Request completes with any response data.​ If any controller responds to their currently executing instruction with a response payload (such as the execution output of an applet), it is bundled and returned to the API client synchronously. If a controller needs more time to process an instruction, it can return a pointer to an operation resource that can be used in a later asynchronous request to the server to locate the response once completed. If a controller chooses to respond to an instruction but is unable to complete it, the response returns immediately to the client app as an error. Tags & Automations​ Automations are a flexible framework for the LAMP platform that allow you to run complex analytics and decision support tools either in reaction to new events in an event stream, or on a periodic schedule. Without having to configure a processing pipeline for system requirements such as CPU, I/O, or RAM, automations abstract the functional logic from data resources and system requirements. Automations support simple, flexible, and portable code that can run on low-power devices such as smartwatches or older smartphones all the way up to large servers and computing clusters in the cloud. These \"applets,\" called Automations, can be written in typical data science programming languages such as JavaScript, Python, and R, with any packages or dependencies automatically bundled within. When installed onto a Resource (that is, a Researcher, Study, Participant, or even an Activity), it is capable of listening to events generated by that Resource. For example, if installed for Participants, one such applet could listen to any SensorEvents or ActivityEvents, or when installed for Activities, it could listen only to anonymized ActivityEvents generated by any Participant. When the Cloud server receives new events, it prepares all Automations that fit the specified event mask and allows them to execute with preallocated hardware limits. Tags as Arbitrary Data on Resources​ Tags are an arbitrary unit of extensibility available to all Resource sub-types. Through string-indexed/keyed subscripting, out-of-line data may be attached to objects in the LAMP Platform as an ad-hoc micro-database. For a flow chart on the usage of Tags, see the figure below. Tags are a powerful tool that may be leveraged by clients of the LAMP Platform to build applets for the Platform as well as smaller apps within such client apps themselves. Data-URI strings in Tags​ Tags may consist of JSON object, array, or primitive types, as well as encoded data-uri strings (to represent binary data like PDFs or MP3s). data-uri strings are normal string primitives but prefixed with data:[;base64], where refers to the binary application file type of the data that follows, such as application/json, text/plain; charset=utf8, or image/svg+xml. If the base64 optional parameter is provided, the contents of the string following the comma are to be base64-decoded when interpreted by the LAMP Platform or clients of the LAMP Protocol. Specifying an optional Accept header type may optionally allow the LAMP server component or other LAMP Protocol vendors to automatically convert such data-uri strings into a binary type. Atomic Indexed Access and Modification​ Furthermore, to support atomic operations on Tags, an indexed modifier version of get & set methods shall exist such that for a Tag whose content is an object, the method GET | POST /type//my.tag.name.here[/someKeyedIndex] shall return or replace only the sub-content of the object but not the whole object represented by the Tag. For JSON arrays, keyed indices shall take the form of continuous numbered indices found in the array itself, including the special index length which shall only return but not replace the length of the underlying array. Through these rudimentary atomic mutation facilities, vendors and clients of the LAMP Protocol may perform basic synchronization without poll-waiting or SSE (Server Sent Events) reconciliation. Automations as Multidimensional Planes of Data within Tags​ Automations shall be represented by their specific LAMP Protocol object schema, but encoded as a plaintext JSON data-uri string with the mime type application/vnd+lamp.automation. When registering or unregistering an Automation’s availability with a LAMP server or other component, the component itself shall maintain a running record of compute images, trigger-points, and code for each Automation. When the Tag containing the Automation data is removed, the Automation itself shall be unregistered and made no longer functional in that instance of the LAMP Platform. The figure below describes the relationship between the static data plan (Tags) and the dynamic data plane (Automations) which leverage the functionality described in prior chapters to perform Just-In-Time intervention, prediction, analysis, visualization, or some other set of relevant functions. This functionality has also been superceded by the TagSpec API. Federated Systems Using the Automation Framework​ Supposing multiple existing systems provided clinically useful sources of data, such as longitudinal imaging repositories or existing Fitbit devices synchronized to the cloud. While data retrieval and ad-hoc storage of “out-of-line” (that is, unrecognized by the Platform, but retaining meaning to its owner) data from within the Platform is simple using the API, it would be simply infeasible to manually verify modified data against multiple specific conditions and run several scripts in the Researcher’s local computer before sending out notifications or awaiting further processing from elsewhere. Instead, the Platform supports, through the Automations framework, a method of dynamically running such scripts as “applets” atop extremely powerful unconstrained hardware not managed by the Researcher or their IT department. In the example above, a combination of two applets and an external Amazon S3 database (unknown to the LAMP Platform) provide the equivalent three step upload-process-analyze functionality of apps such as AWARE, Fitbit, Beiwe, Google Fit, and more. The lamp.anomaly_detection applet is not considered a part of this group as it was written to use only the standard API provided by the LAMP Platform; it contains no knowledge of the other two applets and the external database. The org.aware.upload applet requests preallocation of storage, perhaps on the order of ~5GB, but entirely variable depending on the Participant’s device or historical data uploads. It then returns a response immediately to the requesting smartphone device or internet service with a URL to which it can upload the data. The second applet, org.aware.processing is instead run by the Cloud server every 5 minutes to check if any processing needs to be done in the database, and if so, executes the processing, but otherwise does nothing. This applet converts the uploaded data to LAMP Resources (ActivityEvents or SensorEvents, specifically) and submits them to the Cloud server in bulk. Just as with any other events received by the Cloud server, it will then execute a set of Automation applets — in this case, lamp.anomaly_detection. In summary, with this multi-applet workflow, data is automatically uploaded and stored in an external database wholly maintained by a third-party, subsequently converted to actionable reactive LAMP Sensor or ActivityEvents, and finally analyzed through the same methods as all other data. Edit this page Last updated on Nov 19, 2024 by Juan Previous Components of the LAMP Platform Next Low Power & Connectivity Support Step 1: Sensor events are recorded in real-time. Step 2: Collected events are cached, awaiting server reachability. Step 3: Server receives and processes requests from the app. Step 4: Server coordinates internal components for processing. Step 5: Database records the incoming data. Step 6: The scheduler coordinates and runs automations. Step 7: Applets are launched into a safe environment and run. Step 8: Applet results are saved after being run. Step 9: Applet results are persisted for later access. Step 10: Scheduler updates invocation and audit log. Step 11: Request completes with any response data. Tags & Automations Tags as Arbitrary Data on Resources Data-URI strings in Tags Atomic Indexed Access and Modification Automations as Multidimensional Planes of Data within Tags Federated Systems Using the Automation Framework","s":"How the Platform Works","u":"/develop/how_works","h":"","p":645},{"i":648,"t":"Developing LAMP Scheduling Tasks with Cron Jobs in LAMP On this page Scheduling Tasks with Cron Jobs in LAMP While using LAMP, you may wish to schedule events or scripts to run on a regular basis - for example, analysis scripts or scripts that schedule study participants for different studies based on different criteria. If you are using Portainer to support LAMP, you can use the following method and the swarm-cronjob project to schedule these scripts to run regularly. 1. Create a manager service​ To create a manager service, add the following service to a stack (if you do not have a dedicated cron stack, you may wish to create one).It should look something like this: manager: image: crazymax/swarm-cronjob volumes: - /var/run/docker.sock:/var/run/docker.sock:ro environment: TZ: \"America/New_York\" Image should be crazymax/swarm-cronjob Volume should be /var/run/docker.sock:/var/run/docker.sock:ro The TZ env variable should be set to your local timezone - this will affect the times your scripts run if you specify an hour for them to run. Only do this step ONCE, regardless of how many services you plan to create. 2. Create the script service.​ Second, create the service that will run your script. It should look similar to this: my_analysis: image: python:3.8 command: ['python','/script/my_cool_script.py'] environment: TZ: \"America/New_York\" ANALYSIS_NAME: \"My Analysis\" volumes: - /usr/bin:/script - /var/run/docker.sock:/var/run/docker.sock:ro deploy: mode: replicated replicas: 0 restart_policy: condition: none labels: swarm.cronjob.enable: \"true\" swarm.cronjob.schedule: \"0 3 * * *\" swarm.cronjob.skip-running: \"false\" N.B. To install additional modules not included with the standard python3.8 image (for example), you may wish to run pip install commands through a shell script. Use swarm.cronjob.schedule to enter your cron string Do this step for each service you plan to create. After you update the stack, the script should begin running as scheduled. The service above, for instance, will run at daily at 3 AM. Edit this page Last updated on Nov 19, 2024 by Juan Previous App Gateway Next Creating a Github Release","s":"Scheduling Tasks with Cron Jobs in LAMP","u":"/develop/cron_jobs","h":"","p":647},{"i":650,"t":"Developing LAMP Continuous Monitoring & Intervention Delivery Continuous Monitoring & Intervention Delivery The primary goal of the LAMP Platform remains the integration of continuous monitoring and rapid intervention delivery. Using the various components of the Platform with the mindLAMP app as an interface could suffice in most situations — processing power and battery life unconstrained, as well as constant access to network resources and the results of the processing from a Cloud server. As a Participant actively enrolled in a study uses the app, including interacting with Activities available therein, sensor instruments periodically collect measurements in the background. These data are submitted to the Cloud server which notifies and activates the correct set of Automations in the right order. These could include Visualizations, Predictive Models, or Clinical Decision Support systems that were installed by the Researcher supervising that Participant’s study. Please contact us directly for guidance on delivery of just-in-time interventions. Taking the example of a Big Data-powered Clinical Decision Support (CDS) system, it may ingest a vast amount of passive as well as active data to apply heuristics and derive extracted meta-information, upon which machine learning analysis may detect a critical anomaly requiring clinical intervention and support. After notifying the clinician, this system may notify the Participant with an intervention Activity. As the Participant interacts with the newly suggested intervention, newly recorded measurements from the aforementioned sensor instruments will be synchronized to the Cloud server, and this same CDS system will be invoked again to verify that how successful the feedback was. Supposing a Participant were not able to remain connected to the network frequently, the mindLAMP app may not be able to communicate with the Cloud server responsible for managing the execution of these Automations. Instead, however, a “low-connectivity” mode is entered, and of all the Automations installed by the Researcher, those specifically designated as capable of low-power processing (and written only in JavaScript, accessing no network or disk resources) will be downloaded and version-synchronized whenever possible. It is this lightweight version of the CDS system that will instead be executed, but the same intervention Activity will be presented to the Participant in the same timely manner. This version of the CDS system might instead rely only on simple heuristic such as the value of a single question related to suicidal ideation, as the processing scale of the Big data-powered variant CDS system would be dramatically greater and unsupportable on smartphone devices. Edit this page Last updated on Nov 19, 2024 by Juan Previous Low Power & Connectivity Support Next Building New Activities","s":"Continuous Monitoring & Intervention Delivery","u":"/develop/intervention_delivery","h":"","p":649},{"i":652,"t":"Developing LAMP Components of the LAMP Platform On this page Components of the LAMP Platform The LAMP Platform API Server manages all internal components and inter-component message-passing. Its components are embedded within Docker containers and use Docker Swarm for orchestration. Docker Compose and Kubernetes may also be used to deploy the components. Please see Deployment Recommendations if you do not plan on using Docker. API Server​ The gatekeeper between the internal and external domains. This component is implemented in Node.js. ****All API requests are stateless (i.e. there is no session management) and map to a single response. All requests irrespective of authentication requirement must be accompanied by a client API key. This pre-registered API key is recorded in the audit log with each request and serves as origination reference for resources and events. Using the Credential API, requests that require authentication and authorization are validated. Data transport must be encrypted and decrypted as per security & privacy policy. Database​ The persistent data storage device supporting transient caching and complex querying. This component is implemented by CouchDB, with an alternate implementation for low-power usage in Node.js using the PouchDB framework. This component can instead by substituted using custom adapter code by Redis, Amazon S3, or for low-power usage, a naïve Dictionary/Map object in js. A key-value or document database (noSQL) is most ideal for storage needs of the LAMP Protocol, due to its hierarchical object data and high throughput access and low latency manipulation requirements. To support real-time intervention deployment and management, an intermediate in-memory cache is used to ease the load on main long-term storage databases. Message Queue​ Handles the synchronization of communication between all the above actors in the server layer. This component is implemented by the Redis high performance key-value store, with an alternate implementation for low-power usage in Node.js. Each component upon startup must register itself with the message queue for service discovery. Any component may create any number of topics for which other components may publish messages to or subscribe to. Implementation of database manipulation operations, automation events, and the audit log relies solely on subscription to the global topic; the API Server publishes requests here with a unique identifier awaiting response. Automations Worker​ This component handles scheduled push notification delivery as well as execution of triggered scripts to deliver interventions to patients. A compute platform such as a Docker-enabled system or AWS Lambda is used to handle actual execution of code once bundled. A dependency bundler such as Webpack, PIP, or Packrat is used to bundle each automation’s code to avoid dependency versioning conflicts that could crash or halt execution. This component encompasses: Docker Environment, Attachment Container, Automation Scripts, Scheduler. Repositories​ Frontend Backend Native Core Data Science Programming Libraries Dashboard API Server iOS Cortex R Activities App Gateway Android CollegeStudy JS Python Swift Kotlin The LAMP Platform is designed, developed, and managed entirely as a series of GitHub repositories: Core: LAMP-platform: All issues and documentation across any component repository MUST be centralized here! Acts as the project tracker and documentation hub. package.json: All configuration for the Docusaurus documentation generator is housed here; the docusaurus.config.js file is dynamically generated. openapi.json: This file is dynamically generated from the LAMP-protocol git submodule that contains the openapi.yaml file. blog: This directory contains the release notes/updates/\"What's New\" tab documents. docs: This directory contains all documentation in entirely markdown files. Each file and folder includes a numeric prefix that sorts its order in the documentation sidebar, as well as an assets folder for all relevant images and media. LAMP-protocol: The openapi.yml file houses the OpenAPI specification for the LAMP Protocol, upon which the entire LAMP Platform is built. Backend: LAMP-server: (See Backend section in the documentation for more details on the nature of the component and how the code is organized.) LAMP-worker: (See Automations section in the documentation for more details on the nature of the component and how the code is organized.) LAMP-app-gateway: (See App Gateway section in the documentation for more details on the nature of the component and how the code is organized.) Frontend: LAMP-dashboard: (See Frontend section in the documentation for more details on the nature of the component and how the code is organized.) LAMP-data-studio: LAMP-activities: SDKs: LAMP-js: LAMP-py: LAMP-r: LAMP-swift: LAMP-kotlin: Data Science: LAMP-cortex: (See Cortex section in the documentation for more details on the nature of the component and how the code is organized.) LAMP-ide: A JupyterLab and VSCode-based integrated development environment with extensive support for Cortex. Native Apps: LAMP-core-ios: A Swift-based scaffolding that incorporates support for TypeScript business logic and a WKWebView for the frontend UI. Designed to work well with the LAMP-swift SDK. LAMP-core-android: A Kotlin-based scaffolding that incorporates support for TypeScript business logic and a WebView for the frontend UI. Designed to work well with the LAMP-kotlin SDK. Other: LAMP-college-study: A proof of concept for the Automations framework that is a part of the LAMP Platform. clinical-scales-importer: Automated clinical scale importer that works for RedCap integration into the LAMP Platform. analysis-tools: Misc. analysis tools for working with research studies using the LAMP Platform. Deprecated: LAMP-app: The mindLAMP v1 native app for iOS and Android. DO NOT USE. LAMP-portal: The mindLAMP v1 backend. DO NOT USE. Edit this page Last updated on Nov 19, 2024 by Juan Previous Configuring your server to add Sensors and Activities Next How the Platform Works API Server Database Message Queue Automations Worker Repositories","s":"Components of the LAMP Platform","u":"/develop/intro","h":"","p":651},{"i":654,"t":"Developing LAMP Low Power & Connectivity Support On this page Low Power & Connectivity Support The LAMP Platform API Server encompasses two main purposes: Communicate via the LAMP protocol as an API to any participating clients, and store data in the LAMP protocol data format. As the client of the API Server need not worry about the data storage, the semantics of how the data is stored as well as where, or for how long, are transparent and are subject to change in real-time. As long as the client uses the API, all storage access is transparently cached, proxied, or retrieved from a pre-specified medium. In proxy mode, an instance of the API Server can continue to vend the API without being attached to permanent/long-term storage. This process requires: A data cache, a connection to another instance of the LAMP server, and periodic synchronization between (1) and (2) determined by an availability factor. The proxy mode use-case of the LAMP server enables chaining instances together for accumulative data transfer. This serves useful for several reasons: Network availability no longer impacts the API client as long as sufficient storage space is available for caching. ActivitySpec updates (that is, when the code underlying a cognitive test or intervention, for example, is updated) are automatically propogated to all instances downstream of the first non-proxy instance when synchronization occurs. Thus, an \"application update\" not involving the native code of the API client occurs transparently. Connectivity method is not specifically defined; though it becomes the concern of the specific instance, it allows for flexibility of transfer between WiFi, bluetooth, LTE, etc. as needed or as capable by the hardware. As battery and storage size are concerns that impact the overall cost of a smartphone as well as how often it must be charged, patients with lower economic ability, for example, may not be able to sustain high frequency sensor collection while simultaneously lacking consistent network connectivity. By both lowering the collection frequency of sensors and running an app-local instance of the LAMP server configured in proxy mode, patients will be able to use the same app, automations, and interventions, at a lower but still acceptable fidelity while incurring less battery and storage penalty. In contrast, even in capable devices and well-equipped environments, recording high frequency sensor data from multiple devices still require coordination. Patients would be able to configure the smartwatch instance in proxy mode to connect to the smartphone instance, which itself would be configured in proxy mode to connect to an instance of the LAMP server in the cloud. This daisy-chaining of instances allows the smartphone instance of the LAMP server to effectively \"see\" the data from the smartwatch instance and be able to perform actions in response to it. Limitations & Strategies​ While a server instance in proxy mode appears transparent to any clients, there are a few concerns followed by mitigations thereof: origination: data cached and transferred through several instances in proxy mode would lose meaningful tagging of origin (i.e. from a wearable with high accuracy sensors or a smartphone with low accuracy sensors). the use of an API key carries origination information encoded as a JWT (JSON Web Token) for all clients irrespective of which server instance they choose to communicate with. LAMP server instances must only brand their origination upon data if none exists already. timestamp invalidity: though the root instance of a LAMP server may be geolocated in the EST (U.S. East) time zone, it may be synchronizing with instances configured in proxy mode geolocated in the IST (Indian) time zone. LAMP server instances convert timestamps into the GMT (+0) time zone upon receipt from the client. upon client data access, the LAMP server re-converts timestamps into the local time zone (as specified by an IP address, for example) or the time zone requested by the client. automation support: intensive automations such as those written in Python or R cannot be invoked without network availability at the root instance. some automations, when marked as \"lightweight\" and written in a supported language, such as Javascript, may be locally cached and invoked on-schedule to facilitate critical and vital functions (i.e. intervention deployment dependent on reported suicidal ideation). synchronization of non-timestamp-marked data: update or creation actions on non-event data cannot be synchronized or merged. such actions can be considered completed by the proxy mode instance but will be queued for synchronization with a timestamp; if the root instance rejects the action, the local proxy mode instance will be reconciled with the most recent data. Activity deployment-notification and scheduling: a push notification to deploy an Activity to a patient at the current instance (that is, not a scheduled one) may not succeed if the root instance does not synchronize with the proxy mode instance, and specifically targeting one instance may not be possible (such as the proxy mode instance running on a smartphone instead of on a wearable device, which is unsuitable for interaction). the API key (that is, the origination as explained above) of a suitable client can optionally be specified when pushing a notification; such notifications will remain queued at the root instance until downstream synchronization reaches the correct proxy mode instance. if no origination is required, the first available proxy mode instance with the applicable ActivitySpec will consume the notification and dequeue it (preventing downstream instances from knowing it was ever present). Edit this page Last updated on Nov 19, 2024 by Juan Previous How the Platform Works Next Continuous Monitoring & Intervention Delivery Limitations & Strategies","s":"Low Power & Connectivity Support","u":"/develop/low_power","h":"","p":653},{"i":656,"t":"Developing LAMP Repositories Creating a Github Release On this page Creating a Github Release Process​ On the Github BIDMC Division of Digital Psychiatry homepage, choose the appropriate repository for which you will generate your release. On the repository page, click the 'Releases' tab on the right-hand side. Click the 'Draft a new release' button. In the ‘Release title’ box, name release using the following convention: Release [today’s date’]. Ex: “Release 2022.8.29”. Click ‘Choose a tag’ and create a new tag for that date. Click 'Generate release notes' button. Once the notes are generated and everything looks good, you can click the green 'Publish release' button at the bottom of the page. Edit this page Last updated on Nov 19, 2024 by Juan Previous Scheduling Tasks with Cron Jobs in LAMP Next Writing Documentation Process","s":"Creating a Github Release","u":"/develop/Repositories/creating-github-release","h":"","p":655},{"i":658,"t":"Developing LAMP Repositories Writing Documentation On this page Writing Documentation Documentation formatting needs to be consistent and professional. All documentation is written in markdown. The priority when writing documentation is clarity, and digestibility. Documentation should be no longer than it must be. Process​ In order to post documentation, go into BIDMCDigitalPsychiatry/LAMP-Platform/docs on Github. Each folder within the docs represents a section of the docs website, as shown here. Add a file in the appropriate section folder. Give it a name that corresponds to the order where it will appear in the sidebar. When you are ready to post, go to the bottom of the Github file and select the large green 'Commit new file' button. 'Commit directly to the master branch'. The new documentation should then appear in docs.lamp.digital Edit this page Last updated on Nov 19, 2024 by Juan Previous Creating a Github Release Next OAuth2/OIDC Support Process","s":"Writing Documentation","u":"/develop/Repositories/writing-documentation","h":"","p":657},{"i":660,"t":"Quick Links Frequently Asked Questions On this page Frequently Asked Questions Why are there two mindLAMP apps available? Which one should I use?​ The app that is associated with the LAMP Platform is called mindLAMP. mindLAMP 1 is no longer being used and has been replaced by mindLAMP 2. You will no longer be able to download or use the mindLAMP 1 app in early 2021. How do I transition from mindLAMP 1 to mindLAMP 2?​ If you are using mindLAMP with a web browser like Chrome, Safari, Firefox etc. then it will automatically have updated. If you are using the app, simply download mindLAMP 2 from the App Store or Play Store and log in. Do I need a wearable to collect passive data?​ HealthKit data is only available with wearables with two exceptions: step count and sleep data. Step count can be gathered through your mobile device, and sleep data can be gathered by downloading specific apps on iOS (napbot) and Android (sleep as android). mindLAMP requires WatchOS 7 and WearOS 2. What can I customize to my study or clinic?​ You are able to customize tips in Learn, surveys in Assess, activities in Assess and Manage, and potentially visualizations in Prevent. What's a system administrator?​ This is usually your Information Technology (IT) or Information Services (IS) department at your institution. How do I get login information?​ If you or your organization is self-hosting the LAMP Platform independently, please contact your administrator or IT department for your login information; otherwise, please contact us. How do I reset my password?​ If you are a study participant, please reach out to your research coordinator. If you are a patient, please reach out to your clinician. If you are a research coordinator or clinician, please reach out to your system administrator or IT department. What's a study?​ A study comprises of a set of activities that multiple patients will interact with and receive notifications for, such as surveys or breathing exercises, as well as a set of sensors which will be enabled to collect data on the patients' smartphones or wearable devices. Researchers and clinicians add able to create and manage multiple studies. What's the difference between a survey and an activity?​ \"Activity\" is a broad term that encompasses different items that patients can interact with inside of the mindLAMP app. This includes cognitive tests, mindfulness, meditation, and more. A survey is a type of activity that presents a set of questions for patients or participants to answer. How do I create a survey?​ Click the [+ Add] button at the top right of the list and select \"Survey Instrument\". Can I edit a survey?​ Yes, you can edit it from the activities tab by tapping on its row in the list. We recommend only editing surveys to fix typos or adjust the language of a question or response choice. What happens to my data after I delete a survey?​ Deleting a survey or other activity automatically deletes their response data across all participants or patients. This data is always recoverable — please reach out to your system administrator for help recovering data. How do I delete a survey?​ Select one or more survey instruments you would like to delete and press the trash can icon at the top right of the list. How do I customize an activity?​ Click the [+ Add] button at the top right of the list and select your desired activity. All customization options for a specific activity will be on the screen that follows. There aren't any surveys or activities in my Feed. Why?​ You may need to set schedules for the surveys or activities that you have assigned to your study. Please make sure you're viewing the Feed on a day where one of those schedules is activated to send notifications. Why is my Manage section appearing blank?​ You must add activities for them to show up in a specific tab. If there are no activities created for a specific tab, that tab will remain blank. Who can see my data?​ Your system administrator will only access your personal information to support internal operations, including troubleshooting/user support, and service improvements. To ensure you are receiving the highest level of service in your interaction with the mindLAMP app, the Division of Digital Psychiatry may use your contact information to communicate with you regarding your requests. We also use this data to create aggregated statistics which helps us in the improvement of our service. Does the mindLAMP app work offline?​ The mindLAMP app does not currently work offline. However, this is a highly requested feature that we are working on. Where do I report a bug or request a feature?​ Submit any bugs or feature requests here: Report a Bug or Request a Feature Is mindLAMP 2 available in other languages?​ In addition to English, the mindLAMP app currently supports Chinese (Simplified and Traditional), Danish, French, German, Hindi, Italian, Korean, and Spanish. Is there a page for quick troubleshooting?​ If you require immediate advice on how to solve some commonly encountered issues, please see the Troubleshooting Page Edit this page Last updated on Nov 19, 2024 by Juan Previous Report issues Next Security & Privacy Policy Why are there two mindLAMP apps available? Which one should I use? How do I transition from mindLAMP 1 to mindLAMP 2? Do I need a wearable to collect passive data? What can I customize to my study or clinic? What's a system administrator? How do I get login information? How do I reset my password? What's a study? What's the difference between a survey and an activity? How do I create a survey? Can I edit a survey? What happens to my data after I delete a survey? How do I delete a survey? How do I customize an activity? There aren't any surveys or activities in my Feed. Why? Why is my Manage section appearing blank? Who can see my data? Does the mindLAMP app work offline? Where do I report a bug or request a feature? Is mindLAMP 2 available in other languages? Is there a page for quick troubleshooting?","s":"Frequently Asked Questions","u":"/faq","h":"","p":659},{"i":662,"t":"Setting up mindLAMP Accessing Your Account On this page Accessing Your Account Step 1: Open your phone or desktop browser and navigate to the mindLAMP app.​ The app is available at https://dashboard.lamp.digital/ — consider bookmarking it so you don't forget. Please note that LAMP requires at least Android 7 minimum and soon will require iOS 14 minimum to run on a smartphone. Step 2: Log in with your credentials.​ If you do not have a username and password assigned to you, please contact your systems administrator or IT department. If you or your organization doesn't yet have access to mindLAMP, but would like to try it out first, you can tap [Try It] below the login button. If no domain was specified by your IT systems administrator, you can leave that field blank (\"lamp.my_organization.org\" is only for this example). Edit this page Last updated on Nov 19, 2024 by Juan Previous How does the mindLAMP app work? Next Log In Information, Tips, and Tricks Step 1: Open your phone or desktop browser and navigate to the mindLAMP app. Step 2: Log in with your credentials.","s":"Accessing Your Account","u":"/start_here/accessing_account","h":"","p":661},{"i":664,"t":"Developing LAMP Migrating from CouchDB to MongoDB Migrating from CouchDB to MongoDB Please carefully read and replace the variables in this JS script before continuing: index.js #!/usr/bin/env node const es = require('event-stream') const JSONStream = require('JSONStream') const through2batch = require('through2-batch') //const nano = require('nano')('http://admin:REDACTED_PASSWORD@10.0.0.1:5984/') // STAGING const nano = require('nano')('http://admin:REDACTED_PASSWORD@10.0.0.2:5984/') // PRODUCTION const { MongoClient } = require('mongodb') const MONGO_URL = 'mongodb://USERNAME_REDACTED:PASSWORD_REDACTED@CLUSTER_NAME_REDACTED.us-east-2.docdb.amazonaws.com:27017/LAMP?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false' const DB_NAME = \"LAMP\" // MAKE THE REQUIRED COLLECTIONS AND INDEXES FIRST BEFORE LOADING DATA IN! /* const REQUIRED_INDEXES = { \"researcher\": [ { timestamp: 1 }, { timestamp: 1, _id: 1 } ], \"study\": [ { timestamp: 1 }, { timestamp: 1, _id: 1 }, { timestamp: 1, _id: 1, _parent: 1 } ], \"participant\": [ { timestamp: 1 }, { _parent: 1, timestamp: 1 }, { _id: 1, _parent: 1, timestamp: 1 } ], \"activity\": [ { timestamp: 1 }, { timestamp: 1, _parent: 1 }, { _id: 1, timestamp: 1 }, { timestamp: 1, _id: 1, _parent: 1 }, ], \"sensor\": [ { timestamp: 1 }, { timestamp: 1, _parent: 1 }, { _id: 1, timestamp: 1 }, { timestamp: 1, _id: 1, _parent: 1 }, ], \"activity_event\": [ { _parent: -1, activity: -1, timestamp: -1 }, { _parent: -1, timestamp: -1 }, ], \"tag\": [ { _parent: 1, type: 1, key: 1 } ], \"credential\": [ { access_key: 1 }, { origin: 1 }, { origin: 1, access_key: 1 } ], \"sensor_event\": [ { _parent: -1, sensor: -1, timestamp: -1 }, { _parent: -1, timestamp: -1 }, ], } for (let [collection, indexes] of Object.entries(REQUIRED_INDEXES)) { console.dir([collection, indexes]) db.collection(collection).createIndexes(indexes).catch(err => console.dir(err)) } */ // IGNORE THIS, SEE BELOW INSTEAD const ANALYTICS_IDS = [] async function migrateANALYTICS(db, pID) { let count = 0 nano.use('sensor_event') .findAsStream({ selector: { \"#parent\": pID, \"sensor\": \"lamp.analytics\", }, sort: [{ timestamp: 'desc' }], limit: 100000 }) .on('error', (e) => console.error('error', e)) .pipe(JSONStream.parse('docs.*')) .pipe(es.map((data, callback) => { data._deleted = false data._parent = data['#parent'] delete data._rev delete data['#parent'] callback(null, data) })) .pipe(through2batch.obj({ batchSize: 100000 })) .pipe(es.map((data, callback) => { count += data.length db.collection('sensor_event') .insertMany(data, { ordered: false, writeConcern: { w: 0 } }) .catch(err => err.code === 11000 ? {} : console.dir(err)) console.dir([pID, count, Date.now(), process.memoryUsage()]) callback(null, null) })) .on('end', () => { console.log(`ANALYTICS complete!`) }) } async function check(db, collection) { console.log(`${collection} = ${await db.collection(collection).estimatedDocumentCount()} docs`) //console.log(JSON.stringify((await nano.use(collection).list()).rows.map(x => x.id).sort())) //console.log(JSON.stringify((await db.collection(collection).find({}, { _id: 1 }).toArray()).map(x => x._id).sort())) } async function fixup(db) { await db.collection('researcher').remove({_id: {$regex: /^_design.*/}}) await db.collection('study').remove({_id: {$regex: /^_design.*/}}) await db.collection('participant').remove({_id: {$regex: /^_design.*/}}) await db.collection('activity').remove({_id: {$regex: /^_design.*/}}) await db.collection('sensor').remove({_id: {$regex: /^_design.*/}}) await db.collection('activity_spec').remove({_id: {$regex: /^_design.*/}}) await db.collection('sensor_spec').remove({_id: {$regex: /^_design.*/}}) await db.collection('tag').remove({_id: {$regex: /^_design.*/}}) await db.collection('credential').remove({_id: {$regex: /^_design.*/}}) // THIS WILL BE INCREDIBLY SLOW SINCE WE DO NOT USE INDEXES FOR THESE: //await db.collection('activity_event').remove({_id: {$regex: /^_design.*/}}) //await db.collection('sensor_event').remove({_id: {$regex: /^_design.*/}}) } // FIXME: DO NOT USE THIS; THIS IS A BACKUP ONLY! async function _migrate_old_deprecated() { await MongoClient.connect() const db = await MongoClient.db('LAMP_staging').collection('sensor_event') nano.use('sensor_event') .listAsStream({ include_docs: true }) .on('error', (e) => console.error('error', e)) .pipe(JSONStream.parse('rows.*.doc')) .pipe(es.mapSync(x => { let transformed = [{ _deleted: false, _parent: x['#parent'], timestamp: x.timestamp, sensor: x.sensor, data: x.data }] db.insertMany(transformed).catch(err => err.code === 11000 ? {} : console.dir(err)) })) } async function migrate(db, collection, skip, startkey) { console.log(`${collection} start = ${await db.collection(collection).estimatedDocumentCount()}`) let count = skip || 0 nano.use(collection) .listAsStream({ startkey: startkey, include_docs: true }) .on('error', (e) => console.error('error', e)) .pipe(JSONStream.parse(['rows', /./, 'doc'])) .pipe(es.map((data, callback) => { data._deleted = false data._parent = data['#parent'] delete data._rev delete data['#parent'] if (collection === \"tag\") // HARDCODED FOR TAG ONLY! data.value = JSON.stringify(data.value) callback(null, data) })) .pipe(through2batch.obj({ batchSize: 100000 })) .pipe(es.map((data, callback) => { count += data.length db.collection(collection) .insertMany(data, { ordered: false, writeConcern: { w: 0 }}) .catch(err => console.dir(err)) console.dir([data.slice(-1)[0]._id, count, Date.now(), process.memoryUsage()]) callback(null, null) })) .on('end', async () => { console.log(`${collection} complete = ${await db.collection(collection).estimatedDocumentCount()} docs!`) console.log('PLEASE KEEP THIS TERMINAL SESSION OPEN UNTIL MONGODB HAS LOADED ALL CHANGES!') }) } MongoClient.connect(MONGO_URL, { useUnifiedTopology: true }, async (err, client) => { const db = client.db(DB_NAME) // ONLY ONCE TO MAKE PUSH NOTIFICATIONS WORK CORRECTLY //for (let pID of ANALYTICS_IDS) // await migrateANALYTICS(db, pID) // FIXME: This also copies over CouchDB design documents, _id prefixed with \"_design/\". // USE BELOW LINE TO DELETE THEM FROM A COLLECTION //fixup(db) // CHECKING STATUS ONLY // USE ANOTHER TERMINAL WINDOW TO QUERY PROGRESS WITH A COPY // OF THIS SCRIPT WITH `check(...)` UNCOMMENTED! //check(db, 'tag') // YOU CAN ONLY RUN ONE AT A TIME: //migrate(db, 'researcher') //migrate(db, 'study') //migrate(db, 'participant') //migrate(db, 'activity') //migrate(db, 'sensor') //migrate(db, 'activity_event') //migrate(db, 'tag') //migrate(db, 'credential') //migrate(db, 'activity_spec') //migrate(db, 'sensor_spec') migrate(db, 'sensor_event', undefined, undefined) }) You will likely need to adjust Node options to run the script. export node_options=--max_old_space_size=14000 # set to around ~80% of max limit (default of 2GB WILL FAIL) To automate installation of prerequisite packages, use this package.json: package.json { \"name\": \"couch_mongo_importer\", \"version\": \"1.0.0\", \"main\": \"index.js\", \"scripts\": { \"start\": \"node index.js\" }, \"dependencies\": { \"event-stream\": \"^4.0.1\", \"JSONStream\": \"^1.3.5\", \"mongodb\": \"^3.6.6\", \"nano\": \"^9.0.3\", \"through2-batch\": \"^1.1.1\" } } Edit this page Last updated on Nov 19, 2024 by Juan Previous OAuth2/OIDC Support Next Training Modules","s":"Migrating from CouchDB to MongoDB","u":"/develop/couchdb-migration","h":"","p":663},{"i":666,"t":"Developing LAMP OAuth2/OIDC Support On this page OAuth2/OIDC Support Introduction​ The OAuth2/OIDC integration for the LAMP Platform allows 3rd party identity services systems your organization may already be using (such as Azure Active Directory or AWS Cognito) to be used for authentication and authorization. This integration works by binding an existing mindLAMP ID (such as a Participant ID or Researcher ID) to an existing or new IdP identity (that is, the Participant ID within mindLAMP must still be managed manually from the dashboard at this time). Additionally, when using IdPs such as Azure Active Directory, this integration also supports B2C identities; for example, if your hospital organization already has Azure configured and has just set up the LAMP Platform, patients will be able to use their personal Gmail or Twitter accounts (if allowed by your organization) to sign into mindLAMP on their personal devices. note Support for OAuth2/OIDC is under active development is a BETA feature at this time. For more information and assistance, contact us. Setup​ New variables added to the MindLAMP Environment to support OAuth 2.0 Auth with different IdPs: OAUTH_AUTH_URL This is the URL that that we will use to fetch our authorization code from Example value: https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/authorize OAUTH_TOKEN_URL This is the URL we will use to exchange our authorization code for proper access/refresh tokens Example Value: https://login.microsoftonline.com/common/v2.0/oauth2/token OAUTH_LOGOUT_URL This is the URL will be used when logging out of MindLAMP. Since the session with the provider is handled by the provider (Cookies stored in their domain keep the session open, generally) IdPs have their own logout URLs. Example Value: https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=https://localhost:3001 OAUTH_CLIENT_ID Client ID given to us by our IdP when creating an OAuth Credential/Client OAUTH_CLIENT_SECRET Secret given to us by the IdP when creating an OAuth Credential/Client TOKEN_SECRET Secret that will be used to sign/validate tokens created inside the mindlamp platform Example Value: QfTjWnZq4t7w!z%C*F-JaNdRgUkXp2s5u8x/A?D(G+KbPeShVmYq3t6w9y$B&E)H Can be anything OAUTH_REDIRECT_URI URL that we will be redirected to after authentication with our IdP Example Value: http://localhost:3001/ OAUTH_SCOPE The set of permissions we will be requesting of our IdP Example values and notes: offline_access should always be present, it asks the IdP to emit refresh tokens. For B2C, the Azure Client ID needs to be part of the scope or Azure won't emit Access Tokens OAUTH This value signifies if the API accetps/handles OAuth Login correctly. Example Values: on/off warning All of the values should be strings. Example using Keycloak​ Set up a custom OAuth solution with MindLAMP​ In this example we set up an existing MindLAMP server with Keycloak, an open source identity provider which supports the OAuth 2 flow. This choice is supplied as an example; other OAuth 2 solutions could be used. Create and start the Keycloak server​ The Docker Compose file you need to use depends on whether you want to run the server in development or production mode. Choose the right one below, save it to a docker-compose.yaml file and then run docker compose -f /docker-compose.yaml. Development mode​ Click to expand version: '3' services: keycloak: image: quay.io/keycloak/keycloak:17.0.0 command: start-dev environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: KC_DB: postgres KC_DB_URL_HOST: KC_DB_USERNAME: mindlamp KC_DB_PASSWORD: ports: - 8080:8080 depends_on: - db db: image: postgres:latest environment: POSTGRES_USER: mindlamp POSTGRES_PASSWORD: POSTGRES_DB: keycloak ports: - 5432:5432 Production mode​ Click to expand version: '3' services: keycloak: image: quay.io/keycloak/keycloak:17.0.0 command: [\"start\", \"--auto-build\"] environment: KC_HEALTH_ENABLED: true KC_METRICS_ENABLED: true KC_HOSTNAME: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: KC_HTTPS_KEY_STORE_FILE: /tmp/keystore KC_HTTPS_KEY_STORE_PASSWORD: KC_DB: postgres KC_DB_URL_HOST: KC_DB_USERNAME: mindlamp KC_DB_PASSWORD: ports: - 8443:8443 depends_on: - db volumes: - :/tmp/keystore db: image: postgres:latest environment: POSTGRES_USER: mindlamp POSTGRES_PASSWORD: Password01 POSTGRES_DB: keycloak ports: - 5432:5432 Make sure you match for both containers. In production mode, HTTPS support is mandatory, so you also need to provide a valid key store file. Please refer to https://www.keycloak.org/server/all-config for a complete list of build and configuration options. Set up a realm​ Open a web browser and go to Keycloak hostname (e.g., https://0.0.0.0:8443 if you are in the host in production mode). Click Administration Console. Enter the credentials you specified in the docker-compose.yaml file and click Sign In. On the top left corner of the screen, hover over Master (this is what the default realm is called) and click on the Add realm button that will appear. Enter a name for the new realm (for example, MindLAMP) and click Create. Once the realm is created, you can add one or more clients for the MindLAMP server to interact with. Add an OAuth client​ Click Clients from the sidebar on the left and then click Create on the right. Specify a client ID (for example, spa) and pick openid-connect as the client protocol. Click on Save. Configure the client for MindLAMP​ A few settings need to be set up for the new client to work with MindLAMP. Set Access Type to confidential. Turn on Implicit Flow Enabled. Under Valid Redirect URIs, add an item for every MindLAMP dashboard that will log in through this client. The exact URL(s) must be specified, otherwise log in will be rejected by Keycloak. Set up any other options that are needed. When you are finished, click on Save. Switch to the Credentials tab and copy the client secret. You will need it for the following step. Set up the MindLAMP server​ Finally a few environment variables need to be added to the MindLAMP server. Here's an example of what the OAuth section of the .env file could look like: OAUTH=\"on\" OAUTH_AUTH_URL=\"https://hostname here>/realms/realm name/protocol/openid-connect/auth\" OAUTH_TOKEN_URL=\"https://hostname here/realms/realm name/protocol/openid-connect/token\" OAUTH_LOGOUT_URL=\"https://hostname here/realms/realm name/protocol/openid-connect/logout\" OAUTH_CLIENT_ID=\"client name here\" OAUTH_CLIENT_SECRET=\"client secret here\" OAUTH_REDIRECT_URI=\"dashboard URL here\" OAUTH_SCOPE=\"openid offline_access\" OAUTH_STATE=\"12345\" OAUTH_NONCE=\"67890\" Hostname needs to be the same as specified in the docker-compose.yaml file. The OAUTH_LOGOUT_URL is not mandatory, but it is needed so that the user is automatically logged out from Keycloak when they log out from the dashboard. Remember that OAUTH_REDIRECT_URI must be exactly the same as the redirect URI the client was set up with. For further specifications on configuring Oauth for Google see the documentation here: https://docs.lamp.digital/deploy/configure_oauth_google Kubernetes Example​ mindlamp-server.yml apiVersion: apps/v1 kind: Deployment metadata: name: mindlamp-server labels: app: mindlamp-server spec: replicas: 1 selector: matchLabels: app: mindlamp-server strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type: RollingUpdate template: metadata: labels: app: mindlamp-server spec: containers: - name: server image: {redactedValue}/mindlamp_server:latest imagePullPolicy: Always resources: limits: cpu: \"1000m\" memory: \"2000Mi\" requests: cpu: \"50m\" memory: \"100Mi\" livenessProbe: exec: command: - /bin/sh - -c - \"wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1\" env: - name: CDB value: \"http://admin:varDbPass@couchdb-internal:5984/\" - name: NATS_SERVER value: message-queue:4222 - name: REDIS_HOST value: redis://cache:6379/0 - name: HTTPS value: \"off\" - name: PUSH_API_GATEWAY value: \"https://app-gateway.lamp.digital/push\" - name: PUSH_API_KEY value: \"varPushAPIKey\" - name: ROOT_KEY value: \"varRootKey\" - name: OAUTH_AUTH_URL value: \"https://login.microsoftonline.com/*7BredactedValue*7D/oauth2/v2.0/authorize\" - name: OAUTH_TOKEN_URL value: \"https://login.microsoftonline.com/common/v2.0/oauth2/token\" - name: OAUTH_LOGOUT_URL value: \"https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=api:**B7BredactedValue*7D\" - name: OAUTH_CLIENT_ID value: \"varOauthClientId\" - name: OAUTH_CLIENT_SECRET value: \"varOauthClientSecret\" - name: TOKEN_SECRET value: \"varOauthTokenSecret\" - name: OAUTH_REDIRECT_URI value: \"{redactedValue}\" - name: OAUTH_SCOPE value: \"openid offline_access\" - name: OAUTH value: \"on\" restartPolicy: Always serviceAccountName: \"\" volumes: null Edit this page Last updated on Nov 19, 2024 by Juan Previous Writing Documentation Next Migrating from CouchDB to MongoDB Introduction Setup Example using Keycloak Kubernetes Example","s":"OAuth2/OIDC Support","u":"/develop/oauth_oidc","h":"","p":665},{"i":668,"t":"Quick Links Security & Privacy Policy On this page Security & Privacy Policy Your Personal Information​ “Your information” is the information we request when you initially download and launch the app. It is then accessible from your user profile under ‘Settings.’ This information includes, but is not limited to your user name and user profile you had used to register for the app. We also receive other types of information about you that is customarily gathered by web and mobile applications: We receive data about you whenever you interact with the mindLAMP 2 app, such as when you launch the application, click on, view or otherwise interact with a feature. This may include date and time of the request, the feature requested, and completion status of the request. We receive data from the mobile phone you use to launch mindLAMP 2 app. We receive data about your answers to surveys and cognitive tests. If you opt in, we receive geospatial data that can tell us where you are nearby when you interact with the app. If you opt in, we receive data about your step count and other information provided by Apple Health Kit or Google HealthConnect. How We Use Your Personal Information​ Your personal information may be used to support internal operations, including troubleshooting/user support, and service improvements. To ensure you are receiving the highest level of service in your interaction with the mindLAMP 2 app, your contact information may be used to communicate back with you regarding your requests. We also use the data to create aggregated statistics which helps us in the improvement of our service. Aggregated data allows us to evaluate \"traffic\" patterns to our app in terms of the number and role of visitors, level of demand, most popular requests, and types of errors. These statistics are not linked to any personal information that can identify any individual person. This data may be kept for an indefinite amount of time, and it may also be used at any time and in any way reasonably necessary to monitor for security breaches and to ensure the integrity of the data on our servers. The Division of Digital Psychiatry at the Beth Israel Deaconess Medical Center will never access your data without prior consent and permission. If self-deploying the LAMP Platform, you will be in sole control and ownership of all data consumed or produced by the LAMP platform. We do not by default request, use, or store any personally identifiable information, and strongly recommend against using the user-facing utilities to do so. Google HealthConnect Data​ mindLAMP 2 has access to read information from the following Google HealthConnect sensors (though permission can be revoked for any individual sensor at the discretion of either the researcher or participant): Heart Rate Steps Speed Calories Burned Basal Metabolic Rate Distance Body Fat Hydration Nutrition Blood Glucode Blood Pressure Oxygen Saturation Body Temperature Steps Cadence Sleep Respiratory Rate The use of information received from Health Connect will adhere to the Health Connect Permissions Policy, including the Limited Use requirements. Information We Share With Others​ We do not sell, trade, or otherwise transfer to outside parties any information we receive. We may release information we collect to judicial, law enforcement or other government agencies when we believe release is appropriate to comply with a governmental or court order, or the law, to enforce our own policies, or to protect ours or others’ rights, property or safety. We may share aggregate statistics about our visitors, general traffic patterns, app usage, survey answers, cognitive test results, and phone collected data like step count, geospatial location, flights of steps climbed (and other Apple Healthkit and Google HealthConnect data) for purely research purposes. If used for research, your data will be only used in an aggregate form. We will never use your data for marketing or commercial purposes. How We Protect Your Information​ We make every reasonable effort to protect your information against unauthorized access, alteration, disclosure or destruction using current security technologies. Servers that host the mindLAMP 2 app and store your personal information are maintained in a secured facility behind a firewall. The mindLAMP 2 app security measures are reviewed regularly and are consonant with policies for secure healthcare data storage. Finally, we restrict access to users’ personal information to our employees, contractors and agents who need to know that information in order to process it on our behalf for purposes of providing you support and services. These individuals are required to attend training on patient privacy and confidentiality and are bound by strict confidentiality obligations. Deleting Your Account​ Your account may be deleted via the app through the delete my account button. You may delete your account at any time. You may also request to delete your account externally via the following Google form: https://forms.gle/rb7wSWgHBNwU1cQ78 Can I delete data stored by the LAMP Platform?​ Yes, you can delete any content stored in the LAMP Platform. There is a soft-deletion period of 90 days during which the data is unavailable but may be restored by request. Once the 90 day period ends, the data is deleted permanently, after which it may no longer be recovered. Copyright And Proprietary Rights​ The mindLAMP 2 app, its features and contents are protected by copyright and other intellectual property laws, as well as other state, federal and international laws and regulations. Unless otherwise expressly provided in these Terms of Use, you may print or download information from the app for personal, non-commercial use only, provided you identify the source of the material, include a statement that the material is protected by copyright law, and do not modify any of the information. Reprinting, or otherwise reproducing, and/or reproducing any document in whole or in part is prohibited, unless prior written consent is obtained from the copyright owner. Nothing in these Terms of Use shall be deemed to grant you any right, title, license or interest in or to any software or documentation, or in any related patents, copyrights, trademarks, trade secrets or other intellectual property of any kind. How do I let my IRB know that LAMP is safe to use in a research study?​ Here's some language you might find useful in conveying the LAMP Platform's HIPAA compliance and safety to your IRB. Encrypted information from survey responses and passive data will be sent and stored electronically on a secure server. Responses from individual patients will be identified by a randomized number and contain no personal identifiable information apart from age and gender. Here's another example regarding participant anonymity. The app never records or stores any personal identity information. Every participant is assigned a randomly generated participant ID (for example, “U123456789”), and all participant data are connected only to that ID, not to a name, phone number, or address. Security & Privacy​ The LAMP Platform is free and open source software currently developed by Beth Israel Deaconess Medical Center but does not have any licensing restrictions for intellectual property. LAMP is safe, secure, and easy to use. Though it has broad potential, we will be using it as an interface that patients and clinicians can use together to track data and generate visual reports. It’s important to note that LAMP is not an electronic health record system. Below is an outline of the technical specifications that back privacy and security in the LAMP Platform. Login and Authentication​ Credentials are required to access the LAMP Platform. By default, a clinician can see the data of their patient, but any other access must be explicitly granted. The clinicians are able to view aggregate reports that contain no identifying information about the patients in the site. Technical Safeguards​ As data is transferred between the device and server, it is encrypted in flight using the TLS v1.3 protocol atop the HTTP/2.0 transmission format. As data is accepted by the server, it is stored in the data lake encrypted at rest using AES-256 encryption through a secret key unique to each site. Any requests made to the server to create, update, delete, or even read data, will cause the incremental addition of the request to an audit log, along with the credentials used to make the request so it is possible for a site to monitor all requests for data. Personal Health Information (PHI)​ There are 18 identifiers that make health information PHI. The one PHI type that LAMP will collect are dates as information is timestamped. LAMP will not collect patient names and uses codes instead. Thus, linking any information collected by LAMP to a unique patient is not easy without a key which will be kept by each site and not shared. HIPAA​ LAMP offers physical and technical safeguards that are in line with the HIPAA Security Privacy Rule. Specifically, the rule “requires covered entities to maintain reasonable and appropriate administrative, technical, and physical safeguards for protecting e-PHI including: Ensure the confidentiality, integrity, and availability of all e-PHI they create, receive, maintain or transmit; Identify and protect against reasonably anticipated threats to the security or integrity of the information; Protect against reasonably anticipated, impermissible uses or disclosures; and Ensure compliance by their workforce. LAMP meets this through the offering the follow features: Limited facility access and control with authorized access procedures in place Restrictions for transferring, removing, disposing, and re-using PHI Access control allowing only for authorized personnel to access PHI. Audit reports / tracking logs that record activity Integrity controls in the database that ensure data is not altered or destroyed unless by an authorized user with the appropriate permissions Encrypted network transmissions Breach Policy​ In the event of a suspected data breach, a site lead may immediately revoke all credentials and immediately disable access to the data. As both a public and private key are required to decrypt exported data, and separate private keys are maintained per site and per patient, a data breach of one sub-section of the data cannot and will not affect other sub-sections or the entire platform. Furthermore, devices are identified by a unique per-device token and data integrity in flight can be ensured when reviewing the audit trail by cross-referencing this device-specific token. As noted above, LAMP does not record name but identifies users by codes so even with a breach, it will be hard to connect a person to their data. Risk Analysis and Management​ Our team performs frequent risk analysis as part of our security management processes. We take the following steps to mitigate risk: Daily review of logs for all BIDMC-hosted research and clinical sites to pinpoint potential risks. Determine the probability of a major security issue occuring. Frequent security updates to proactively prevent new threats to LAMP's security. Security Threat Protocol​ In the unlikely event of an active security threat, our team will take the following steps: Determine how and what information has been endangered. Alert users with steps (if any) they must take, such as changing their passwords. Identify and complete the necessary steps our team must take to secure our server, dashboard, and data. Log the type of threat, when and how it occured, and the resolution. Edit this page Last updated on Nov 19, 2024 by Juan Previous Frequently Asked Questions Next How does LAMP Platform Work? Your Personal Information How We Use Your Personal Information Google HealthConnect Data Information We Share With Others How We Protect Your Information Deleting Your Account Can I delete data stored by the LAMP Platform? Copyright And Proprietary Rights How do I let my IRB know that LAMP is safe to use in a research study? Security & Privacy Login and Authentication Technical Safeguards Personal Health Information (PHI) HIPAA Breach Policy Risk Analysis and Management Security Threat Protocol","s":"Security & Privacy Policy","u":"/privacy","h":"","p":667},{"i":670,"t":"Setting up mindLAMP Activities: Tips, Surveys, and Cognitive Tests Take Surveys and Complete Activities On this page Take Surveys and Complete Activities Step 1: View your Feed.​ Now that you've logged into mindLAMP, you'll immediately see the Feed. Along the tab bar, you'll find buttons that link you to all the things you can do within mindLAMP. They're organized into the following sections: Learn: You may find helpful tips to apply to your lifestyle here. Assess: You'll find check-in surveys and games to play here. Manage: You'll find relaxing activities to clear your headspace here. Prevent: You'll find resources to help receive care and manage your symptoms here. In the Prevent tab you'll find data visualization tools. Step 2: Take a survey or use a relaxing Activity.​ When you tap one of the buttons, you'll be taken to a full-screen Activity. One example is the breathe exercise in the Manage section (shown below), but you can also try taking surveys from the Assess section (shown below). Please note that some survey instruments can contain description information along with option anchors, as shown in the image below. Surveys with many questions and options are best taken on desktop, laptop, or tablet computers as they could be difficult to answer when taken on a mobile device. Each day that a survey or activity is completed, an encouraging streak tracker will pop up showing the number of days in a row that the patient has take the survey or completed the activity. This streak tracker is unique for surveys and activities. In other words, if a patient completes a mood tracker survey for seven days in a row and an anxiety survey for five days, their respective streak pop ups will show different numbers. Streak popups can be customized in that they can be turned on or off for activities. Within groups, each activity can have their own streak. The streak title and description can also be changed by editing the respective \"Streak title\" and \"Streak Description\" fields shown below. Edit this page Last updated on Nov 19, 2024 by Juan Previous Customize and Schedule Activities Next Visualize data Step 1: View your Feed. Step 2: Take a survey or use a relaxing Activity.","s":"Take Surveys and Complete Activities","u":"/start_here/activities/complete_activities","h":"","p":669},{"i":672,"t":"Setting up mindLAMP Activities: Tips, Surveys, and Cognitive Tests Activities Currently Available on LAMP On this page Activities Currently Available on LAMP Assess​ Balloon Risk​ Box Game/Spatial Span​ Cats and Dogs​ DBT Diary Card​ Emotion Recognition​ Jewels A​ Jewels B​ Maze​ Memory game​ Pop the Bubbles​ Spin the Wheel​ Surveys​ Symbol-digit substitution​ Voice recording​ Manage​ Journal​ Mindfulness/Breathe​ Anchoring Ambience Breathe with Your Body Breathing Exercise Calming Your Body Forest and Nature Sounds Inner Teacher Kindness Loving Kindness Mountain Meditation Positive Thinking Nature Relaxation Scratch Card​ Activities Coming Soon Assess​ 3D Figure Copy​ Digit Span​ N-Back​ Serial 7s​ Simple Memory​ Temporal Order​ Trails B​ Trails B Dot Touch​ Visual Association​ Manage​ Goal Setting​ Hope Box​ Medication Tracker​ Edit this page Last updated on Nov 19, 2024 by Juan Previous Visualize data Next Affirmations Assess Balloon Risk Box Game/Spatial Span Cats and Dogs DBT Diary Card Emotion Recognition Jewels A Jewels B Maze Memory game Pop the Bubbles Spin the Wheel Surveys Symbol-digit substitution Voice recording Manage Journal Mindfulness/Breathe Scratch Card Assess 3D Figure Copy Digit Span N-Back Serial 7s Simple Memory Temporal Order Trails B Trails B Dot Touch Visual Association Manage Goal Setting Hope Box Medication Tracker","s":"Activities Currently Available on LAMP","u":"/start_here/activities/activities","h":"","p":671},{"i":674,"t":"Setting up mindLAMP Activities: Tips, Surveys, and Cognitive Tests Create and Customize Activities On this page Create and Customize Activities How to add an Assess cognitive test from the Patient Profile How to add a Manage activity from the Patient Profile If you would like to create your own custom activity, you can do so by writing it in html/javascript. There is no required structure or framework; as long as it is in html/javascript it will work with LAMP. Survey instruments and other Activities in the LAMP Platform afford you automatic version control. In other software or when managing “paper & pencil” data, it is typically difficult, if not impossible, to track changes to survey questions or survey responses when administered with a patient. Create a New Activity for the Assess and Manage tabs​ Log in to the dashboard and navigate to the Activities tab. Click the [+ Add] button at the top right of the list to begin. If you would like to edit an existing activity, simply tap on its row in the list instead. Select an activity like the DBT Diary Card or a cognitive test like Jewels for the Assess tab. Select an activity like Mindfulness for the Manage tab. If you would like to create a group of activities, click Activity Group. Note, you can add surveys and activities to an activity group. This group of activities can then be scheduled like a survey or other activities. Customize Which Tab an Activity Appears in How to customize which tab on LAMP an Activity Appears in If you would like to customize which tab an activity appears in, you can do so by clicking the pencil icon next to the activity you would like to move. Next, check the box next to \"Customize which Tab this Activity sppears in\". Finally, click the dropdown to display all tab options. There are four tab options to choose from: Assess, Learn, Manage, and Portal. Check off the box next to the desired tab you would like the activity to appear in. Note that you can select no tabs, which hides the activity. This can be helpful if there are schedules assigned to a particular activity. It can also be helpful if there are several surveys grouped together, and you only would like the group to appear. Note that you can also display the activity on multiple tabs. Finally, click the \"Save\" button on the bottom right. Edit this page Last updated on Nov 19, 2024 by Juan Previous Delete and Schedule Activities Next Customize and Schedule Activities Create a New Activity for the Assess and Manage tabs","s":"Create and Customize Activities","u":"/start_here/activities/create_activities","h":"","p":673},{"i":676,"t":"Setting up mindLAMP Activities: Tips, Surveys, and Cognitive Tests assets Affirmations On this page Affirmations Affirmations are positive words that you say to yourself to achieve success. Affirmations are used to remind yourself of your strengths and your worth. Affirmations are something that you want to be true. They are spoken as statements of fact which help you to believe in them. Affirmations can help when you are feeling down about yourself, nervous, or even when you are excited about the day ahead. Steps​ Choose at least one affirmation such as: I accept myself for who I am. I have a lot to be proud of. I have the power to make my dreams come true. I am resilient. I have people who love, support, and respect me. I am a loving and caring person. I control my own happiness. I believe in myself. I make a difference. Practice saying your affirmation at least once a day or more by slowly repeating the affirmation numerous times. Let it sink into your mind and body. Hang your affirmation in your room, store an image of it on your phone, or keep a copy in your wallet. Practice​ Practice Affirmations once a day or more at times when you are feeling well and not distressed. This will help you learn the skill better so you will be able to use Affirmations in harder situations when you really need it. The more you practice, the more Affirmations become second nature and you can use them anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Alternative Explanations Alternative Explanations (Alt-Ex) is a skill that can help you to think about situations in a different way. This will help you control your feelings and reactions to that situation. Alternative Explanations can help you to feel less stressed and anxious. Alt-Ex can also help you to clear your head a bit so you can think straight. Here is an example: You leave a message for your brother and he doesn’t return your call. Do you jump to conclusions and think “he’s ignoring me?” Do you feel upset and angry? Do you act on these thoughts and feelings? “I’m going to ignore him.” For many situations, you don’t know what happened but before you “jump to conclusions,” slow down and think about other things that could be going on. Be creative! Here is the example again: You leave a message for your brother and he doesn’t return your call. Possible explanations could be: My brother lost his phone and never received my message. My brother is at the dentist and can’t talk right now. Steps​ Think of a situation in your life that causes you to “jump to conclusions.” Identify one or more possible explanations to the situation. Be creative. Practice​ Practice Alt-Ex once a day or more at times when you are feeling well and not stressed. This will help you learn the skill better so you will be able to use Alt-Ex in harder situations when you really need it. The more you practice, the more Alt-Ex becomes second nature and you can use it anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Belly Breathing Often when you are anxious, the result in your body is that your breathing rate increases, and you take shorter, shallower breaths. When you are relaxed, the opposite happens. By slowing down the breath, you trick your brain into thinking you are relaxed, and all the relaxation neurochemicals are released. Belly Breathing is a technique you can use to relax and become more aware of your breathing. Belly Breathing can help you to calm and center yourself when you are feeling overwhelmed or stressed. Steps​ Sit comfortably and straighten your back. Place your hands on your belly and slow your breathing down. Inhale fully and gently breathing through your nose. Keep your breaths smooth and steady while feeling your belly and chest expanding. Exhale fully and slowly blowing all the air back out of your lungs. Let your belly sink down flat. Practice​ In the beginning, try to practice Belly Breathing for five minutes at least once a day. Letting your breath fill your body will give you the calmness you need to face social situations, a job interview, or even the world. It’s hard at first but take your time and try again. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Breathing Retraining Breathing Retraining is a skill that helps you to slow down your breathing so you can clear your head a bit, think straight, and feel more relaxed. Breathing Retraining can be used anytime and anywhere so you feel less stressed, worried, or upset. Steps​ Choose a word that you find relaxing, such as “calm” or “peace” or another word of your choice. Take a normal breath (not a deep one) in through your nose and exhale slowly through your mouth. While you exhale, say the relaxing word you have chosen very slowly: “calm” or “peace.” Pause briefly before you take your next breath. You can count to four before taking in each new breath. Practice this exercise several times a day, taking 10 to 15 breaths at each practice. Practice​ Practice Breathing Retraining once a day or more at times when you are feeling well and not stressed. This will help you learn the skill better so you will be able to use Breathing Retraining in harder situations when you really need it. The more you practice, the more Breathing Retraining becomes second nature and you can use it anytime, with ease. Reference: Jennifer Gottlieb PH. D Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Compassion Compassion is the ability to feel the emotions of another person. When you are compassionate, you can take the perspective of another and you have the desire to help. Being compassionate makes you feel good and can help you to handle stress. Using strategies to be compassionate can improve your health, well-being, and personal relationships. Compassion starts with appreciation, gratitude, and self-love. Some compassion strategies you can practice include: Give back or volunteer for a greater purpose Model kindness to others. Practice at least one small act of kindness every day to make someone’s life better (i.e. write a positive note, give a compliment, offer to help, say kind words, hold the door) When you wake up or go to bed, write down at least one thing that you are grateful for, that you appreciate about your life, and what you’ve been given. Think about someone you care about (i.e. a partner, friend, parent, or even a beloved animal). Focus on them and direct your attention towards them with three basic feelings and thoughts: may you be well, may you be happy, and may you be free of suffering. Choose a compassionate phrase such as “Be kind whenever possible. It is always possible” (Dalai Lama). Practice saying your compassionate phrase as many times as possible each day. Think of a time when someone was kind to you. Recall how it felt to receive that kindness including the things this person said, the feeling of the emotion in the person, and the experience. Steps​ Choose one Compassion Strategy. Practice your Compassion Strategy every day. Try different Compassion Strategies to see which one works for you. Practice​ Practice Compassion Strategies every day. This will help you make Compassion Strategies a part of your everyday routine. If a daily practice is made of showing kindness, it will eventually become something that is done without much thought and effort. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Coping Strategies Life is persistent in teaching you lessons. Life is like school for the soul; it will keep presenting you with the same stressful problems until you finally learn what you need to learn. When problems show up repeatedly, don’t take it personally, just know that there is more for you to learn. Developing Coping Strategies can help you to manage problems and cope with stress. Examples of strategies for coping and stress relief include: Get enough sleep. If possible, try to go to bed and get up at the same time. Remember that alcohol and caffeine add to sleep problems. Reduce your caffeine and sugar. Eat meals or snacks throughout the day. Hunger and low blood sugar can increase stress and negative emotions. Increase your fun. Every day do something you really enjoy. Try to see the humor in situations and people. Laughter is a great stress reliever. Take a short media fast. Turn off the phone, the TV, and the computer occasionally. Breathe. When stressed, most people take short, shallow breaths. This reinforces anxiety. Do the opposite and take some long, deep breaths whenever you remember to during the day. Spend some time out in nature. Relax by taking a walk outside or sitting in the sun. Sit next to a tree or pond and look at the sky or the water. Get moving. Research has proven that exercise is a better anti-depressant than medications for mild to moderate depression. Write your thoughts and feelings down. Writing can help you clarify things and can give you a renewed perspective. Turn to spirituality for comfort. Attend a service, pray, talk to God, or ask for help or grace. Consider taking time to meditate, relax, or practice mindfulness. Steps​ Choose one Coping Strategy at a time. Practice your Coping Strategy at least once a day or as often as possible. Try different Coping Strategies to see which one works best. Practice​ Practice your Coping Strategy at least once a day when you are feeling well and not distressed. This will help you make Coping Strategies a part of your everyday routine. The more you practice, the more Coping Strategies become second nature and you can use them anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Distraction Techniques Distraction Techniques are strategies used to take your mind off distressing thoughts and overwhelming feelings. Distraction Techniques can provide a break from intense emotions by focusing your mind on something else. Distraction Techniques are a way to pass the time and to provide structure. Remember, Distraction Techniques are a short term or “in the moment” strategy to get you through a difficult period. Distraction Techniques should not be used for the long-term to avoid problems and emotions. Examples of Distraction Techniques include: Flick an elastic band around your wrist Flash cards with positive messages Squeeze a rubber ball very hard Talk or go out with a friend Take a bath or shower Exercise or yoga Hold ice in your hand Read or write Clean your room or the house Listen to music Steps​ Choose one Distraction Technique. Practice your Distraction Technique every day. Try different Distraction Techniques to see which one works best for you. Practice​ Practice Distraction Techniques once a day or more at times when you are feeling well and not distressed. This will help you learn the skill better so you will be able to use Distractions Techniques in harder situations when you really need it. The more you practice, the more using your Distraction Technique becomes second nature and you can use it anytime, with ease. Reference: understandingcbt.com Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Grounding Grounding is an in the moment strategy used to “anchor” you to the present and improve mental focus. When you are overwhelmed, grounding is one way to gain a sense of control and safety. Grounding puts healthy distance between you and negative feelings. It can be a phrase you say, an action you do, or something you visualize in your mind. Examples include: Grounding Saying Count to 10 or say the alphabet, very s…l…o…w…l…y. Say a safety statement. “My name is ______; I am safe right now. I am in the present, not in the past.” Read something, saying each word to yourself slowly. Say kind statements as if you were speaking to someone else, “you are a good person going through a hard time. You’ll get through this.” Say a coping statement: “I can handle this.” “This feeling is temporary.” Grounding Action Stretch such as roll your head around or extend your fingers. Touch various objects around you like a pen, keys, your clothing, or the wall. Carry a grounding object in your pocket, which you can touch whenever you feel triggered. Listen to soft and slow music. Focus on your breathing, notice each inhale and exhale. Grounding Thoughts Think of favorites like color, animal, season, food, or time of day. Picture people you care about, look at a photograph. Think of things you are looking forward to in the next week-perhaps time with a friend, going to a movie. Steps​ Choose one Grounding technique (saying, action, or thought) at a time and give it your full attention. When grounding, focus on the present, not the past or future. Keep your eyes open, scan the room, and turn the light on to stay in touch with the present. Practice your Grounding technique for at least ten minutes every day. Try different Grounding Strategies to see which ones work for you Practice​ Practice Grounding once a day or more at times when you are feeling well and not distressed. This will help you learn the skill better so you will be able to use Grounding in harder situations when you really need it. The more you practice, the more Grounding becomes second nature and you can use it anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Mindfulness Autopilot Autopilot is a type of mind state when your attention is only partially aware of the present moment and what is around you. When you are on Auto-Pilot you are preoccupied and just “going through the motions.” You are acting on habit and without intention. Some examples of being on Auto- Pilot include stressing, worrying about what will happen, daydreaming, or being lost in your own world. In a car, we can sometimes drive for miles “on Auto-Pilot,” without really being aware of what we are doing. In the same way, we may not be really “present” moment-by-moment, for much of our lives: We can often be “miles away” without knowing it. When you are on Auto-Pilot emotionally, it is easy to “slip” into moods, become lost in your emotions, and wrapped up in your thoughts. You are more likely to have your “buttons pressed” and unhelpful thinking may lead to worsening mood. When you no longer know what you are feeling or why, it is easy to become disconnected. When you become mindful of your actions and get off Auto-Pilot you become empowered to make positive change. You respond to situations with choice in new and beneficial ways. Steps​ Choose one activity each day that you often do in Auto-Pilot. Examples include; brushing your teeth, eating a meal, showering, preparing for bed, or walking in the park. Stick with one activity for a week or longer rather than changing the activity regularly. When the time comes for that activity, do it in a fully present frame of mind. Pay attention to the activity itself and what is happening in the present moment. This includes what is occurring around you (touch, sight, sound, taste, smell) and what is occurring within you (physical and emotional sensations). If you start to think of other things, then note it for a second and return to the sensations of the activity. If the activity is likely to be longer than a few minutes, then practice the first two minutes mindfully. Practice​ You can get off auto-pilot by practicing over and over again every day to change the focus of your attention; be present and aware; and be open and accepting. The more you practice getting off auto-pilot, the easier it will be to act with intention all the time. Reference: stillmind.com.au, mindfulnessmuse.com, Crane, R. (2009). Mindfulness-based cognitive therapy. New York, NY: Routledge., and awakenedsource.com Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Mindfulness Five Senses The Five Senses is a mindfulness meditation exercise that helps to calm your mind and focus on your environment instead of your thoughts. The Five Senses will help you to become aware of your surroundings and notice things that never stood out before. This technique can be repeated any time and any place you need a quick relaxation or stress break. Steps​ Sit or lie in a comfortable position. Take a few deep breaths to help you relax. Notice your surroundings and what is occurring. What can you see around you? Is it a clear day? What is on the walls? How is the light reflecting? What objects are in the room? What can you feel? How does your clothing texture feel? Is the table surface smooth? Do you feel the pressure of your feet? What can you hear? Do you hear an appliance humming? The wind outside your home? Leaves rustling? Music playing in the distance? What smells are in the air? Inhale slowly. Exhale. On the next inhale, what do you smell? What do you smell immediately? What scents do you perceive in the distance? Do this for about 10 breaths. What can you taste? Begin to focus on your mouth and the sensations you taste in your mouth. Do you taste the remnants of a recent beverage or meal? Was it sweet or salty? Breathe in and out two more times being aware of all the wonderful things around you. When you are ready, take a final deep breath and get back to your day with renewed energy and a relaxed state of mind. Practice​ Practice Five Senses once a day or more at times when you are feeling well and not distressed. This will help you learn the skill better so you will be able to use Five Senses in harder situations when you really need it. The more you practice, the more using Five Senses becomes second nature and you can use it anytime, with ease. References: clayton.edu, therapistaid.com Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Mindfulness Mindfulness is a skill that is used to increase your awareness and ability to focus on the present or being fully attentive to one thing at a time. When you are being mindful, you concentrate your mind, give all your attention, and let go of distracting thoughts. Mindfulness is a skill that can be learned and is helpful to boost mood, increase happiness, and strengthen control of your mind. Mindfulness strategies include: While eating, focus your attention on the taste, smell, and texture of your food as you are chewing. When you are in a group, or a conversation, focus your attention on the very moment you are in with the other person. Do a chore and pay attention to every detail. Observe your movements and sensations. Set a timer for three minutes and simply begin to write down every thought that goes through your mind on a piece of paper. Breathe mindfully by counting your breaths, focusing on the physical act of breathing, and being aware of any thoughts that arise while breathing. Sit very still and notice one thing that you can see, hear, taste, and smell. Make a gratitude list or journal. Steps​ Choose one Mindfulness strategy. Practice your Mindfulness strategy at least once a day or as often as possible. Try different Mindfulness strategies to see which one works best. Practice​ Practice Mindfulness strategies once a day or more at times when you are feeling well and not distressed. This will help you make Mindfulness strategies a part of your everyday routine. Start with 2-3 minutes of practice and build up to a longer duration. The more you practice, the more Mindfulness strategies become second nature and you can use it anytime, with ease. Reference: The Miracle of Mindfulness: A Manual of Meditation by Thich Nhat Hanh,1976, Boston, Beacon Press 1976; McKay, M., Woo The dialectical behavior therapy skills workbook 2007. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Optimisim Optimism means to be hopeful, positive, and confident about the future. Optimism is believing that you have control over your own happiness and being certain that good things will come your way. Feeling optimistic can help you improve your mood, enhance your health, and increase your confidence. Optimism also improves relationships as others prefer optimistic people to negative ones. Developing an optimistic attitude takes time. Some strategies include: Try to approach challenges believing you will succeed. View a tough situation as a challenge you can figure out how to handle. Remember that facing challenges is a normal part of life and growth. Surround yourself with optimistic people who have a positive attitude and believe in you. Dedicate energy to changing negative thinking to more positive thinking. This can take lots of practice! Focus your energies on the things in life you can control rather than dwelling on the things you can’t. Use humor and laughter to lift yourself up. Steps​ Choose one strategy to improve your optimism. Practice your chosen Optimism Strategy at least once a day or as often as possible. Try different strategies to improve your optimism to see which one works best. Practice​ Practice optimism strategies once a day or more at times when you are feeling well and not distressed. This will help you make Optimism Strategies a part of your everyday routine. The more you practice, the more Optimism Strategies becomes second nature and you can use it anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Positive Self Talk Self-talk are thoughts you have with yourself inside your head. Self-talk is your minds response to a situation or conversation. Self-talk can be positive or negative and can make you feel better or worse. Positive Self-Talk is talk that happens to yourself in an uplifting, calm, and reasonable way. Positive Self-Talk moves you toward emotional control. Negative Self-Talk is talk that happens to yourself in a way that is not helpful or motivating. Negative Self-Talk moves you towards unpleasant emotions and actions. One way to change your behavior and your feelings about a situation is to change your self-talk. With practice, you can train your mind to use Positive Self-Talk. Steps​ Choose at least one Positive Self-Talk phrase that will improve your life such as: Bottom line – I’m in control. Easy does it – Getting upset or mad won’t help. Stay calm- Take a deep breath and relax. Stay cool – don’t make any judgments. I can manage this. No matter what other people say, I know I’m a good person Choose a Positive Self-Talk phrase and practice saying it as many times as possible each day. Hang your Positive Self-Talk phrase in your room, store an image of it on your phone, or keep a copy in your wallet. Try different Positive Self-Talk phrases to see which one works best for you. Practice​ To change how you feel, change what you think or do! You can replace negative Self- Talk with Positive Self-Talk. Practice Positive Self-Talk once a day or more at times when you are feeling well and not distressed. This will help you learn the skill better so you will be able to use Positive Self-Talk in harder situations when you really need it. The more you practice, the more Positive Self-Talk becomes second nature and you can use it anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Positive Thoughts Positive Thoughts are ideas in your mind that make you feel good. Positive Thoughts are good for your brain and mood. Positive Thoughts improve happiness, success, peace, and health. With practice, you can train your mind to think Positive Thoughts. Steps​ Choose at least one Positive Thought that will improve your life such as: Cool Thought: “It’s just not worth it. Take a few deep breaths and chill out.” Escape Route: “It’s OK to take a time out. Move away, get your act together, and then come back and deal with it.” Self Confidence Thought: “I can handle this – I have what it takes to get through this.” New Explanation: “I can cut them some slack – I would hope they’d do the same for me if I was having a difficult time.” See the Whole Picture: “Maybe I need to look at the other side. There might be more to this.” People Doing their Best: “They’re just doing what they know how to do.” Choose at least one Positive Thought. Practice saying your Positive Thought as many times as possible each day. Hang your Positive Thought in your room, store an image of it on your phone, or keep a copy in your wallet. Try different Positive Thoughts to see which ones work for you. Practice​ Practice Positive Thoughts once a day or more at times when you are feeling well and not distressed. This will help you learn the skill better so you will be able to use Positive Thoughts in harder situations when you really need it. The more you practice, the more using Positive Thoughts becomes second nature and you can use it anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Progressive Muscle Relaxation Progressive Muscle Relaxation is a deep relaxation technique used relieve tension and stress from the body. In Progressive Muscle Relaxation exercises, you tense up one muscle group at a time and then relax them. Progressive Muscle Relaxation can help to manage symptoms related to anxiety, depression, sleep problems, headaches, chronic pain, and more. Steps​ Relax Find a quiet place with as few distractions as possible. Sit or lie in a comfortable position. Allow yourself to settle in and become calm. Take a few slow, deep breaths. Start to concentrate on your body. Apply tension to each muscle group, one group at a time. When you are ready, begin with tensing one section of your body. The easiest way to start is with your head and move down your body to your feet or the reverse, from your feet to your head. Feel the tension build and hold for five seconds. Release the tension. Take a deep breath and as you exhale let the tension go. Relax the muscles and keep it relaxed for approximately 10 seconds. It may be helpful to say something like “Relax” as you relax the muscle. Pay close attention to how the muscles relax as the tension flows away. Move to different muscles in your body- first tensing the muscles and then relaxing the muscles. Practice​ Practice Progressive Muscle Relaxation daily or more often for 10 to 20 minutes per day. You can use a recorded guide or practice a relaxation sequence by memory. Through repetition and practice you will learn to recognize a tensed muscle and a completely relaxed muscle. With this knowledge, you can physically relax your muscles at the first signs of tension and with physical relaxation comes mental calmness. Reference: Williams D & Carey M. (2003). “You Really Need to Relax: Effective Methods.” Centre for Clinical Interventions (www.cci.health.wa.gov.au) Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Self Soothing Strategies Self-Soothing strategies are skills used to relax your body and your mind. Self-Soothing strategies are positive ways to cope with every day stress. Self-Soothing strategies can also help you feel at ease when you experience intense emotions. Examples of Self-Soothing strategies include: Something to Hear Something to Taste Something to Smell Something to Touch Something to See Play an instrument Drink tea, hot chocolate, or a smoothie Bake cookies or bread Change into comfortable clothing Art Listen to soothing music Eat your favorite foods Flowers Pet your dog or cat Go to a museum Listen to sounds of nature Chew sugar free gum Fresh smells of nature Take a bath or shower Go window shopping Sing to yourself Suck on peppermint or sour candy Lavender or Lemon oil Stress ball Happy pictures Perfume Use lotion Look at nature Read a good book Star gaze Watch a funny movie Watch a sunset or sunrise Steps​ Choose at least one Self-Soothing strategy. Practice your Self-Soothing strategy at least once a day or as often as possible. Try different Self-Soothing strategies to see which one works best. Practice​ Practice Self-Soothing strategies once a day or more at times when you are feeling well and not distressed. This will help make Self-Soothing strategies a part of your everyday routine. The more you practice, the more Self Soothing Strategies become second nature and you can use them anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Symptom Tracker A Symptom Tracker is a tool you can use to understand your physical and/or mental health symptoms. Using a Symptom Tracker can help you explore your patterns of symptoms and the impact of symptoms on your life. Tracking symptoms helps you to be accurate when you recall what happened and how you felt. It will empower you to feel confident and communicate symptoms with your supports to find solutions that work for you. Exploring your symptoms is a helpful step when looking over your tracker. Example of exploring questions include: What did you experience (i.e. thoughts, behaviors, emotions, or physical feelings)? What caused symptoms (i.e. events, conflicts, or stressors)? What warning signs did you notice? How did symptoms impact your life? What was helpful/not helpful to manage your symptoms? What progress did you make this week with managing symptoms? Steps​ Create your Symptom Tracker by choosing a symptom tracking method (i.e. phone, tablet, computer, journal, notebook, calendar, planner). Record your symptoms as frequently as possible (at least once a day). Use exploring questions to get to know your symptoms. Think about what you experienced, how often symptoms occurred, and under what circumstances. Share your results with your supports to brainstorm helpful coping strategies. Practice​ Track your symptoms every day. This will help you to know when they are happening so you can take the steps to manage them. Over time, recognizing your symptoms and managing your symptoms will become second nature. Date Time Symptom Level of Distress (1=low to 5=high) Notes Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Thought Stopping Thought Stopping is a technique used to change unhelpful thoughts, negative beliefs, or rumination. Thought Stopping techniques help you to get you back on track when your thoughts become overwhelming. Thought Stopping can be a phrase you say, an action you do, or something you visualize in your mind. Examples include: Thought Stopping Saying Say “slow down” when a thought occurs. Say “stop!” either aloud or to yourself. Say “delete negative thought” and replace it. Take a slow deep breath and say a peaceful thought out loud or in your mind. Thought Stopping Action Snap a rubber band around your wrist. List unwanted thoughts on paper. Then list replacement thoughts that are realistic and positive. Sing your favorite song. Thought Stopping Visual Imagine that you see a red Stop Sign. Create a bubble around your thought. Press the bubble, burst it, and watch it float away. Think of a more pleasant thought. Steps​ Choose at least one Thought Stopping technique Practice your Thought Stop ping Technique for at least ten minutes every day Try different Thought Stopping techniques to see which ones work for you. Practice​ Practice Thought Stopping once a day or more at times when you are feeling well and not distressed. This will help you learn the skill better so you will be able to use Thought Stopping in harder situations when you really need it. Negative thinking can become a habit that is hard to break. It may take weeks or months of practicing the Thought Stopping technique for it to work. Don’t give up! You can be successful. Reference: American Psychological Association Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 3-Step Control 3-Step Control is skill to use if you experience auditory hallucinations (hearing voices) that cause anxiety, distress, or distraction. 3-Step Control helps you to focus your attention, feel better, and improve how you interact in the world. Completely eliminating voices altogether might not be possible but lowering the volume so you can focus on your day is achievable! Steps​ When practicing 3-Step Control, use your senses and movement to pay full attention to the task. Your mind’s thinking and your body should become fully engaged. This reduces distractions such as voices and improves control of your thinking. Rate how much your voices distract you on a scale of 1 (low) to 5 (high) For 2 to 10 minutes or until you run out of objects, use your body and mind to attend to one object at a time. Look at an object Point to the object Name the object out loud Rate your voices on the 1-5 scale again. Do you notice any positive change? Practice Understanding when and how you experience voices can help you to gain knowledge about how best to manage them. Practice 3-Step Control at least once a day, when you are not experiencing hearing voices or during a time that voices are not problematic. The goal is to get into the habit of using the skill so you can become more comfortable with it. The more you practice, the more 3-Step Control becomes second nature and you can use it anytime, with ease. Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020 Edit this page Last updated on Nov 19, 2024 by Juan Previous Activities Currently Available on LAMP Next Adding a Sensor Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps Practice Steps","s":"Affirmations","u":"/start_here/activities/assets/VinfenTips","h":"","p":675},{"i":678,"t":"Setting up mindLAMP Activities: Tips, Surveys, and Cognitive Tests Customize and Schedule Activities On this page Customize and Schedule Activities To create any activity that shows up on the manage page (e.g. Jewels A or B): Log in to the dashboard and navigate to the Activities tab. Click the [+ Add] button at the top right of the list to begin. Choose the activity you would like to add. Select the study you wish to add it to. Add a title. Add a description if it is appropriate. Add an icon by clicking on the camera icon and uploading your desired image. Click Save to save your activity. See some examples of different activities below. Some examples of activities you can customize:​ Note: You are able to change the icon by clicking the trash can to delete the current one. From there follow the same steps as above for adding your own icon. Please note that any image you wish to upload must be less than 1mb in size and either a png, svg, or jpeg file type. Jewels A and Jewels B​ For both Jewels A and Jewels B, you are able to input specifics such as game duration. You can also edit the number of diamonds, points, and shapes of the diamonds. To edit any of these, simply click on the box and enter your desired number. Breathe (Mindfulness)​ You are able to either copy a URL and paste it into a breathe activity, or you can upload a previously recorded audio file by selecting \"Upload Audio\" and importing it. Journal​ Once you create your journal activity, it will show up in the Manage tab. However, you are only able to view the results in the Prevent tab. Scheduling an Activity Log into the dashboard and navigate to the Activities tab. Select the activity you would like to schedule by checking the box next to it's name. Click the arrow to the right of the Name. Click the plus sign to the far right to add a schedule. Select you Start Date, Time, Repeat Interval, etc. Click the check mark. The patient or participant will receive a feed item and a notification on their phone at the specified time. How to schedule an activity from the Patient Profile Edit this page Last updated on Nov 19, 2024 by Juan Previous Create and Customize Activities Next Take Surveys and Complete Activities Some examples of activities you can customize: Jewels A and Jewels B Breathe (Mindfulness) Journal","s":"Customize and Schedule Activities","u":"/start_here/activities/customize_activities","h":"","p":677},{"i":680,"t":"Setting up mindLAMP Activities: Tips, Surveys, and Cognitive Tests Create and Customize Surveys Create and Customize Surveys How to Create a Survey from the Patient Profile Need some inspiration to create your survey? Browse our Survey Instrument Library Survey instruments and other Activities in the LAMP Platform afford you automatic version control. In other software or when managing “paper & pencil” data, it is typically difficult, if not impossible, to track changes to survey questions or survey responses when administered with a patient. Log in to the dashboard and navigate to the Activities tab. Click the [+ Add] button at the top right of the list to begin. If you would like to edit an existing survey, simply tap on its row in the list instead. Select Survey Instrument to add a survey to the Assess tab. If you would like to import a survey or activity, click \"Import Activities.\" Create a New Question for Your Survey. Log in to the dashboard and navigate to the Activities tab. Click the [+ Add] button at the top right of the list to begin. If you would like to edit an existing survey, simply tap on its row in the list instead. Select the study you wish to add the survey to. Title your survey. Press the blue (+) icon at the bottom of the list to create a new question. To go back and edit a question, press its title or question number. You can add description content to each question or option choice that can assist clinicians or patients in their selections. If such the description content field is left empty, it will not be displayed when a question or option choice is presented. Please double check and ensure you have no typos or errors when saving the new survey. Once you press the [Save] button, you will be returned to the screen displaying the list of Activities in your clinic or study, now with the newly added survey. If you need to update your survey to add new questions or remove questions, consider making a new survey instead, to avoid changing the intention of the survey or the analysis of its data. Question Types When selecting the question type, please note the following: TEXT questions prompt the individual with a free-form text box within which up to a paragraph content may be written, including emoji characters. BOOLEAN questions prompt the individual with a \"Yes\" or \"No\" option; if you require a different true/false scale or custom text, please use LIST. LIKERT questions prompt the individual with a 4-point scale; the number of points cannot be modified, so if you require a different Likert scale or a custom scale, please use LIST. LIST questions allow a custom list of options to choose from, each with its own description or anchor, and prompt the individual with a vertical list of radio buttons. MULTISELECT questions allow a custom list of options from which one or more choice can be made from a vertical list of checkboxes, each with its own description. SLIDER questions act exactly like LIST questions, except they display a slider of options. SHORT ANSWER questions act exactly like TEXT questions, except they have a shorter character limit (about a sentence). RATING questions allows the individual to rate their response on a custom like LIST questions, except they only display numerical rating options. TIME questions prompt the individual with a box in which only text for hours and minutes \"HH:MM\" is accepted, either in military time or in standard time, MATRIX questions allow several survey items to be grouped together in a table with the same set of instructions and answer choices. The first survey item can have any question type except for \"Matrix\", and subsequent survey items must have the \"Matrix\" question type. Delete an Individual Option in Your Question's List of Options: Press the trash can icon to the right of the outlined \"Question Option\" text box. Click the Publish button or press the ← icon at the top left to cancel Return to the list of existing survey instruments. Edit this page Last updated on Nov 19, 2024 by Juan Previous Create and Customize Tips Next Delete and Schedule Activities","s":"Create and Customize Surveys","u":"/start_here/activities/create_surveys","h":"","p":679},{"i":682,"t":"Setting up mindLAMP Checking LAMP battery and data usage Checking LAMP battery and data usage Though LAMP is designed to be lightweight and use low amounts of data and battery life, users who wish to see how LAMP uses data and battery life on their device may do so by one of the following device-dependent methods. iOS Devices Battery Usage Open the 'Settings' app. In the sidebar on the left-hand side, find and click on the 'Battery' tab. Scroll down the 'Battery' page until you see the 'Activity by App' entry, then tap on 'Show Battery Usage' to show percent of battery used by each app on your device. Scroll down the list to locate the LAMP app Data Usage Open the 'Settings' app. In the sidebar on the left-hand side, find and click on the 'Cellular' tab. Scroll down the list to locate the LAMP app and view its data usage. Android Devices Battery Usage Open the 'Settings' app. Scroll down to and click on 'Battery'. Click on 'View Detailed Usage' and scroll down the list to locate the LAMP app. Data Usage Open the 'Settings' app. Click on 'Wi-Fi and internet'. Click on 'Data usage'. Click on 'Cellular data usage' and scroll to find the LAMP app. Edit this page Last updated on Nov 19, 2024 by Juan Previous LAMP Updates Tutorial Next Modifying the frequency of a sensor's data collection","s":"Checking LAMP battery and data usage","u":"/start_here/battery_data_usage","h":"","p":681},{"i":684,"t":"Developing LAMP Training Modules Training Modules On this page Training Modules 💡 For the best experience viewing these modules, tap the module icon below and use the [Open as page] button in the top left toolbar. ⚠️ Please be sure to view the video AND read the text/articles. Depending on your level of experience, it may take close to two full work days (~16 hours) to complete all modules; plan accordingly! Name Length UNIX & Shell 130 minutes Cloud Computing 80 minutes Docker & Kubernetes 105 minutes DevOps & Git 55 minutes Databases & APIs 80 minutes Pandas & Vega 150 minutes TypeScript & React 100 minutes Code Etiquette & Review 80 minutes Team-specific Resources 110 minutes Markdown Resources​ → Learn any X (programming language, file format, etc.) quickly. UNIX & Shell Length: 130 minutes UNIX is everywhere — if you're using a Mac, you're on a UNIX computer. Linux is one of the big three operating systems (macOS, Windows, Linux) based on UNIX. Even if you're on a Windows computer, you might still be able to use Linux! For our purposes, Linux and UNIX are synonymous (often just shortened to *nix). To begin working with a Unix-based system, we need to learn some basics about files and the shell. https://www.youtube.com/watch?v=dDwXnB6XeiA Everything is a File​ ~30 minutes \"This is the Unix philosophy: Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.\" UNIX Philosophy [expand to read more] Make each [tool] do one thing well. To do a new job, build afresh rather than complicate old [tools] by adding new features. Expect the output of every [tool] to become the input to another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input. Design and build [tools] to be tried early, ideally within weeks. Don't hesitate to throw away the clumsy parts and rebuild them. Use tools in preference [over] unskilled help to lighten a programming task, even if you have to detour to build the tools and expect to throw some of them out after you've finished using them. While there are MANY important tools (executables) you can use to automate tasks or diagnose problems, for example, it can be difficult to know HOW exactly to use them. Read the article below to learn more about how to... learn more! about these tools you'll encounter. How to learn Unix tools https://www.youtube.com/watch?v=42iQKuQodW4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=40&t=40s Directories & Dotfiles​ ~10 minutes All UNIX systems follow the same standardized directory structure (even your Mac, try it!). You will inevitably encounter most of these directories in practice, even if you're working only with data science tools. When you work with developer tools on the command line, you'll need to configure them on the command line. These configuration are stored in your home directory prefixed with a . (dot). The most common ones you will see are .gitignore, .bashrc, .env, and .ssh (a directory of configuration files). .env files are important for local configuration and testing for the LAMP Platform (or Cortex). Read the article below to learn what a .bashrc file is. What is .bashrc file in Linux? - JournalDev Processes​ This is a list of things your executable code is provided when it's transformed into a live process. Parent: when you launch a process, it ALWAYS has a parent. A process can also have many children. Arguments: when you launch a process, you can provide command line arguments to it, which are strings. The shell translates this line echo hello world → into this argument list [\"/bin/echo\", \"hello\", \"world\"], where the first element of that list is the location of the binary code for the executable. Exit Code: when your process exits, it returns a status code (integer) about why it exited (0 indicates success, anything greater than 0 indicates an error). Environment Variables: when you launch a process, it inherits a customizable set of variables from the current executing environment. Current Directory (cwd): this informs the process of the current directory it's being executed from. Path List ($PATH): when you call a binary in the shell (or import some library in Python), it needs to figure out where the executable code is located, and looks up a customizable list of paths to figure that out. File Descriptors: these are the default data streams created for your process and are actually virtual files. Input (stdin = 0): this is an optional input file or stream of data. Output (stdout = 1): this is where print statements go! Error (stderr = 2): this is where exceptions and errors go! Exercises​ ~50 minutes ⚠️ Follow along here. Play-With-Docker gives you access to a virtual Linux computer so you won't cause harm to your computer. Now you're ready to learn practical examples of these tools; the quick tutorial below will help you learn the basics. You can paste each line into the terminal one by one. 🔥 READ EACH COMMENT FIRST BEFORE RUNNING THE COMMAND OR YOU MAY IRREVERSIBLY DAMAGE YOUR COMPUTER! Some commands will require files like \"file.txt\" to be present — you can create files in the Terminal using touch test.txt. Learn X in Y minutes Where X=bash This section below contains list of the most useful or important commands our research group uses in real life. Take a look at them and try some of them out! https://www.youtube.com/watch?v=sXQxhojSdZM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=23&t=68s Regular Expressions​ ~15 minutes RegEx allows you to work with files and strings to find and replace text. On the command line, you can use the old-fashioned grep, or instead, the more advanced RipGrep/All (rg, rga) to quickly find and search across entire directories and through binaries, photos, and PDFs! Use RegExr if you need a quick cheatsheet or a tester tool to try out a RegEx before accidentally damaging 150+ files. Yes, this has happened before, and this is why we use Git (which you will learn soon) to roll-back to a previous version. → Exercise: Try to write a RegEx to select filenames ending in .docx or .doc (Word files). RegExr: Learn, Build, & Test RegEx Solution (Don't peek!) ^.*\\.(doc|docx)$ CRON Schedules​ Another kind of \"pattern string\" you'll see a lot is a CRON schedule (and they're used extensively in the LAMP Platform for things like push notification scheduling and automations!). CRON is a system service that runs scripts for you at the schedule you set, using a cron schedule expression. The syntax is quite simple, but once you've read the Overview section of the article below, use the interactive expression editor to play around with it. cron - Wikipedia → Try to come up with a cron schedule expression for: At every 30th minute past hour 5 and 15 on every 3rd day-of-month from 1 through 31 in every 3rd month from January through December. Crontab.guru - The cron schedule expression editor Solution (Don't Peek!) /30 5,15 1-31/3 1-12/3 * https://www.youtube.com/watch?v=-txKSRn0qeA&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=39&t=1s File Editors​ ~5 minutes ⚠️ Watch until 2:05 only. Editing files on the command line will require you to learn to use a basic text editor like Vim. If you're a beginner, nano is a much simpler but less featured text editor. Another trick is to use cat to save a file quickly. Copy the text you want to paste into the new file. Execute cat > file.txt. (Or use >> instead of > to APPEND to an existing file.) Paste the text. You'll see your file contents in the terminal now. To correctly save the file, press CTRL-D. https://www.youtube.com/watch?v=tzq4asJegKY&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=37&t=8s Open Source​ ~10 minutes Though unrelated to actually using Unix, open source is intertwined with almost all the code and tools we use as a team. There's a lot to unpack about how open source works, but knowing how open source, licensing, and 'forking' repositories works is important behind-the-scenes knowledge. https://www.youtube.com/watch?v=emFMHH2Bfvo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=44&t=11s Important File Formats​ ~10 minutes While this may appear to have nothing to do with UNIX at first, there are a number of essential file formats that lay the groundwork for the modules to come. In addition to SVG (which is best explained visually), take a brief pass at the syntax for Markdown (human-readable text documents), JSON (human-readable structured data transfer format), and YAML (human-readable configuration file format). For Markdown, we also use a documentation generator called Docusaurus that provides additional features, such as embedding tabs, live code blocks, admonitions, automatic table-of-contents, and much more. (Also, Markdown tables can be quite annoying, so use this GUI tool instead to edit those — always stick to compact mode.) Learn X in Y minutes Where X=markdown Markdown Features introduction | Docusaurus Whenever possible, avoid JSON for configuration files, only using it as a data storage or transfer protocol; use YAML instead for configuration files. Learn X in Y minutes Where X=json Learn X in Y minutes Where X=yaml Useful Linux Commands # # SECTION: BASIC COMMANDS # NOTE: Use CTRL-C (not CMD-C on macOS) to end a process in the console. # NOTE: Use CTRL-D (sends an \"EOF\") to quit the shell or console input. # # Get the current UNIX Epoch Timestamp. date +%s # List everything in detail in the current directory. ls -al . # Create a folder AND all non-existant folders along the way. mkdir -p ./my/nested/folder # Create file1.txt touch ./my/nested/file1.txt # Change to a new directory \"nested\" within \"my\" within current dir (\".\"). cd ./my/nested # Concat­enate files ending in .txt (using the * wildcard) and output to console. # NOTE: This command is most powerful when combined with I/O redirection (below). cat *.txt # Copy file1.txt (in ./my/nested) to file2.txt (in a parent directory, \"..\"). cp file1.txt ../../file1.txt # DO NOT RUN THIS: Change directory to the parent of the parent of the current dir. cd ../.. # RUN THIS INSTEAD: Quickly switch back to the directory we were in before. # NOTE: The - trick works with git checkout as well to switch branches! cd - # Get the file type of file1. file file1.txt # Change when file1.txt was last edited. touch -d \"30 minutes ago\" file1.txt # Move (rename) file1.txt to file2.txt. mv file1.txt file2.txt # Paginate file1.txt so it fits on screen and scrolls. less file1.txt # Output last lines of file1.txt as it changes in real-time. tail -f file1.txt # Delete file1.txt. rm file1.txt # Delete a non-empty directory and all of its contents. # WARNING: This will delete everything in ./my! rm -rf ./my # Exit the current shell. (This might close your terminal window too!) exit # # SECTION: I/O REDIRECTION # NOTE: \"cmd\" in this section refers to any command. # # Breaking a comamnd into multiple lines using \"\\\". cmd \\ --arg1 \\ --arg2 # Run cmd1 then cmd2. cmd1; cmd2 # Run cmd2 ONLY IF cmd1 is successful. cmd1 && cmd2 # Run cmd2 ONLY IF cmd1 is not successful. cmd1 || cmd2 # Use file as stdin for cmd (instead of console). # The file will be created if it does not already exist. # If the file already exists, its contents will be overridden. cmd < file # Use file as stdout for cmd (instead of console). cmd > file # Sending stdout to the special file /dev/null discards it. cmd > /dev/null # Append stdout to a file. # This does not overwrite the file if it exists, and instead adds to it. cmd >> file # Use file as stderr (error output) for cmd (instead of console). cmd 2> file # Send stdout to same place as stderr. (Rarely used.) cmd 1>&2 # Send stderr to same place as stdout. (Commonly used.) cmd 2>&1 # Send all output (both stdout and stderr) of cmd to file. cmd &> file # Pipe the stdout of cmd1 to cmd2. cmd1 | cmd2 # Equivalent to the above: use output of cmd1 as file input to cmd2. cmd2 <(cmd1) # Pipe the stderr of cmd1 to cmd2. cmd1 |& cmd2 # The `tee` command sends its stdin to both the file and the console. cmd | tee output.log # # SECTION: PROCESS MANAGEMENT # NOTE: \"cmd\" in this section refers to any command. # # See your shell command history (this is saved in ~/.bash_history too). # NOTE: This is incredibly useful to backtrack and document in Notion something you did while diagnosing a problem or setting up some code/package. history # Show current enviro­nment variables. env # Output value of $NAME variable. Try it with $HOME or $PATH! # $PATH = executable search path; $HOME = current user's home directory. echo $NAME # Set $NAME to value. (NOTE THE MISSING DOLLAR SIGN HERE.) export NAME=value # View an interactive system monitor (CPU & RAM usage per-process). top # `ps` prints all processes and `grep cmd` shows ONLY `cmd` specifically. # NOTE: You need to do this to grab the process ID for below commands. ps -aux | grep cmd # Kill sends an \"interrupt\" to a process ID allowing it to exit cleanly. kill 43273 # The KILL modifier tells the kernel to force-quit the process immediately. kill -KILL 43273 # Instantly force-quit all processes matching the name \"cmd\". killall cmd # # SECTION: ADVANCED COMMANDS # # Run your last command as root (sudo). # NOTE: the \"!!\" shell keyword is replaced by the previously-run command. sudo !! # Recursively find files matching a RegEx pattern or string. # NOTE: If you have RipGrep installed, use \"rg\" instead of \"grep\". # RipGrep: https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md grep \"hello world\" /home/* # Download a file using cURL or wget (only one may be installed on your system). curl -O https://cdn.keycdn.com/css/animate.min.css wget -o https://cdn.keycdn.com/css/animate.min.css # cURL allows you to make HTTP requests. \"-X\" sets the HTTP Method. # Add new headers with \"-H\" and send JSON data using \"--data\". # NOTE: We use single quotes for data because it won't conflict with double quotes. curl -X POST \\ \"api.lamp.digital\" \\ -H 'Authorization: Basic USERNAME:PASSWORD' \\ -H 'Content-Type: application/json' \\ --data '{\"hello\": \"world\"}' # Permissisons: chmod and chown. # Enable a file to become executable. (Otherwise ./my_script.sh won't work.) chmod +x my_script.sh # Recursively set permissions of ~/.ssh to 400 (Google chmod to learn more!) chmod -R 400 ~/.ssh # Recursively set ownership of /home/username to the username. chown -R username:username /home/username # Check the file size of a folder or file (or use wildcard for multiple folders). du -sh my_folder_or_file du -sh /home/* # Check the current disk space usage of ALL disks. df -hT # Find large files (greater than 10M, can be modified to your needs). find / -size +10M -ls # Soft-restart the system (the kernel will reboot instead of the hardware.) # NOTE: NEVER hard-reboot an EC2 instance from the AWS console! Always do this. reboot # # SECTION: SYSTEM SERVICES # NOTE: \"application\" here means any system service. Usually \"docker\". # # List all system daemons (background services). sudo systemctl list-units --all # Check the status of application. sudo systemctl status application # Start application in the background. sudo systemctl start application # Stop application. sudo systemctl stop application # Restart application (if something has broken, for example). sudo systemctl restart application # Reload the configuration for application. sudo systemctl reload application # Enable or disable application to auto-start on reboots. sudo systemctl enable application sudo systemctl disable application # Check the system logs for application. # \"lines\" sets the maximum number of lines we want to view. # \"since\" and \"unit\" set the time boundary for logs. # \"follow\" allows you to watch incoming logs in real-time. sudo journalctl --unit application \\ --lines 50 \\ --since \"09:00\" \\ --until \"1 hour ago\" \\ --follow Cloud Computing Length: 80 minutes All of the LAMP Platform and all of the Cortex data science we do as a team runs in the Cloud... but what is the Cloud? To put it simply, it's simply \"someone else's computer.\" We pay Amazon Web Services (AWS) to host our computers for us so that, by the click of a button, we can create new computers and hard drives, and also delete them, in exchange for a monthly credit card bill. https://www.youtube.com/watch?v=1pBuwKwaHp0&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=9&t=11s Cloud Paradigms​ ~25 minutes We're a research group. Our focus is on the research we do, the data we collect and the analysis we perform on it. We shouldn't have to focus on running servers and diagnosing network errors and crashes. So we pay someone else to do that for us! 💡 Our team has used every layer of Amazon's cloud computing in some way, shape, or form (only in the us-east-2 region, however). Our collaborators and partners, however, may not use Amazon at all — some remain \"on-prem\" (their own servers), or Microsoft Azure, or Google Cloud. The LAMP Platform is architected in a way that remains \"platform-agnostic,\" allowing anyone across these Cloud providers to run LAMP. 💡 Two major concerns arise with Cloud providers: security (IAM) and billing. Managing these for our own tools and systems is still the responsibility of our team. ⚠️ A MAJOR reason we do our data science in the Cloud is Egress billing: data transfer out of AWS IS EXTREMELY EXPENSIVE. Not to mention, the 25 GB/s uplink to other networking and storage resources would be wasted. https://www.youtube.com/watch?v=EOIja7yFScs&t=142s Three parts make up cloud infrastructure: Compute, Networking, Storage. Let's imaging an application (or data analysis tool) as a road trip. You'll need some form of transportation to complete your road trip. You can think of: \"IaaS\" [Infrastructure as a Service] as leasing a car for three years and using it to take several road trips over time. \"PaaS\" [Platform as a Service] as renting a car each time you take a road trip. \"FaaS\" [Functions as a Service] as taking a taxi from point-to-point during your road trip. Some road trips, such as a tour of New England, may be cheapest and fastest when taking a taxi point-to-point, but others, such as going cross-country twice a year, might be cheapest and most effective when outright leasing a car. https://www.youtube.com/watch?v=XRdmfo4M_YA Amazon Web Services​ ~15 minutes The example presented in this video about Computer Vision training is strikingly similar to the kinds of behavioral data analysis we currently (and aim) to do in our research group. We use AWS as our Cloud Provider, and the two guides below will help you better understand which weirdly-named services does what thing, and why (or why not) you should use it. The good parts of AWS - A visual summary Amazon Web Services In Plain English https://www.youtube.com/watch?v=keeqnciDVOo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=26&t=1s Networking​ ~15 minutes Computers in the Cloud work almost exactly the same as the computer (or phone!) you're using right now to access this page. While multiple programs (executables) can run together easily on a single computer, networking allows multiple computers to talk together. https://www.youtube.com/watch?v=2llWuivdS7w From the very basics of \"provisioning a node\" (aka \"renting a computer\") in the Cloud, it's important to understand how IP addresses and ports work. The computer also has 65k ports that identify services (i.e. executables) on the system. Many services reserve certain ports, for example, port 80 is reserved for HTTP (websites), and port 25 is reserved for SMTP (email). List of TCP and UDP port numbers - Wikipedia A socket is the combination of an IP address and a port number. When Computer A (IP 75.124.87.210) connects to Computer B (IP 3.12.74.150) to download a web page (port 80), a socket is created on both computers to transfer the data. https://www.youtube.com/watch?v=JKxlsvZXG7c&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=30&t=16s Servers are just computers that are designed to handle public incoming traffic (usually HTTP, aka web pages). Load balancers are just public-facing servers that redirect incoming traffic to different internal protected servers. While this tutorial is about NGINX, we use Traefik, a similar load balancer with more advanced features and easier configuration. Traefik allows you to serve more than just static files: it can link databases, containers, and other tools to the outside world. Instead of configuration files, Traefik \"hooks into\" Docker to automatically discover which domain names map to which containers. https://www.youtube.com/watch?v=5EqAXnNm0FE https://www.youtube.com/watch?v=FLp88DzvtUk Storage​ ~10 minutes All data (in the form of files) need to live somewhere to be modified and accessed by a computer. Cloud providers like Amazon (AWS) offer storage in three different ways. Each of these storage types have very different performance, cost, and usage characteristics. S3: Object Storage (i.e. databases) Cheapest but offers the least performance, and thus is often used to archive petabytes of data. Any number of computers may read or write objects without mounting the drive. 💡 Fun fact! Most of the internet (web pages, media such as YouTube, etc.) all run on Object Storage, specifically AWS S3. EBS: Block Storage (i.e. standard hard drives or SSDs) The most standard and compatible storage, because it emulates a hard drive. You can format the block storage from the operating system and work with files and directories, or just write blocks of raw data to the storage. Only one computer may mount the storage drive at a time. EFS: File Storage (i.e. network file shares) The most expensive by far, but allows multiple computers to mount and use the storage drive simultaneously. Emulates a network file share, natively giving the operating system a view of files and directories. https://www.youtube.com/watch?v=HmxkYNv1ksg https://www.youtube.com/watch?v=Lb-Pnytoi-8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=2&t=87s Managing Resources​ ~15 minutes It's really easy to quickly click the shiny buttons on the AWS Management Console and provision hundreds of databases and nodes and thousands of terabytes of storage and so on. You can even provision orbital satellites, robots, and quantum computers! Therein lies the problem: how do you keep track of all of these things, and how do you make sure that everyone is on the same page about what provisioned service is being used to do what, and especially, how much they all cost per month? What if there are bugs in the application or data analysis code that run up massive bills and they go un-noticed? Please fix the AWS Free Tier before somebody gets hurt Docker & Kubernetes Length: 105 minutes Containers (Docker) and container orchestration (Kubernetes, Docker Swarm) are a distinct microcosm of cloud computing, and this is where UNIX skills, networking concepts, and more, come together to breathe life into a pile of code through Dockerfiles and docker-compose.ymls. 💡 **→ Wherever you see or hear Kubernetes, replace it in your head with Docker Swarm. ⛔️ Kubernetes** is a container orchestration tool built by Google for Google-scale companies (millions of containers and business-critical data) that requires tremendous expertise to wield correctly. ✅ Docker Swarm is a much simpler (with less features) scaled-back version that makes far more sense for data scientists and individual research teams like ours. https://www.youtube.com/watch?v=Gjnup-PuquQ&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=24&t=2s https://www.youtube.com/watch?v=0qotVMX-J5s Docker​ ~10 minutes Virtual machines allow you to run multiple virtual computers, like AWS EC2 instances, on top of one hardware computer. They're \"heavyweight\" — meaning, they require you to virtualize everything from hard disks to USB ports to graphics, to separate one virtual computer from another. Containers follow the same concept, allowing you to run multiple \"lightweight\" \"computers\" on top of a shared Linux kernel that only really virtualize the file system. They're much lighter, faster, and simpler to use. Your Code ↳ Docker Container ↳ AWS EC2 Virtual Machine ↳ Hardware Rack https://www.youtube.com/watch?v=gAkwW2tuIqE&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=25&t=2s Dockerfiles​ ~25 minutes ⚠️ Follow along here. Play-With-Docker allows you to use Docker without installing it on your personal computer. Let's learn how Docker works in practice by creating a container and running it. Follow along with this tutorial (BOTH from the video and the link below) to learn how to create and work with Dockerfiles and create containers from them. Hello World in Docker Notes about this tutorial: Use git clone to download the example materials to the Play-With-Docker instance. When you see URLs like http://127.0.0.1:3000/ There's an \"open port\" option at the top of Play-With-Docker that you should use to generate a link to port 3000 instead of actually going to the link specified. You'll likely want to bookmark these two references as they will help you work with Dockerfiles and docker-compose.ymls. Dockerfile reference Compose file version 3 reference https://www.youtube.com/watch?v=PziYflu8cB8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=29&t=2s https://www.youtube.com/watch?v=kBF6Bvth0zw Container Orchestration​ ~10 minutes Orchestration of containers is where things get really interesting, since now with a single Dockerfile we can \"shrink-wrap\" application environments to run anywhere on any computers. Similarly, a docker-compose.yml file (which refers to a type of configuration file and not a filename itself; you can rename them to whatever.yml) allows you to \"shrink-wrap\" and describe how many of these application environments deploy and work together. → Why did we choose Docker Swarm over Kubernetes? It's built-in to Docker and takes one command per node to set up the cluster. Lessons learned from using Docker Swarm mode in production | Bugsnag Blog Getting started with swarm mode → Docker's command line tools are also compatible with Kubernetes, so using Docker-specific configuration is perfectly acceptable, even if another team wants to deploy the same thing on Kubernetes. Simplifying Kubernetes with Docker Compose and Friends - Docker Blog https://www.youtube.com/watch?v=aSrqRSk43lY Docker Compose Files​ ~45 minutes ⚠️ Follow along here. Play-With-Docker allows you to use Docker without installing it on your personal computer. While watching these videos, replace the Kubernetes-specific terms with the Docker-specific terms below. Master Node → Manager Node API Server & Kubelet → Docker Daemon Pod → Container kubectl → docker (the command line tool) Load Balancer → (ignore this; docker does this automatically) ClusterIP → (ignore this; docker does this automatically) NodePort → (ports parameter for docker service) Ingress → (we use Traefik which relies on docker service) https://www.youtube.com/watch?v=NPFbYpb0I7w Once you're finished with these videos, try this practical example in Play-With-Docker or on your computer. mogensen/docker-handson-training → To learn how to set up a Traefik ingress, follow along with this guide. Docker - Traefik https://www.youtube.com/watch?v=CdBtNQZH8a4 https://www.youtube.com/watch?v=bvVgP4tw_Hc&t=47s Microservices​ ~15 minutes Now we've learned how to make containers and how to orchestrate them... but what kind of code goes inside of one of these containers? How exactly ARE they talking to each other? Where Microservices are flexible and use container orchestration to achieve performance and scalability, Monoliths (i.e. the \"old way\" of doing things) are installed and run at the IaaS layer, or directly on a computer/node. It's difficult to manage, upgrade, maintain, and debug. The rules below dictate how best to design microservices, and you may recognize how philosophically related these rules are to the Unix philosophy of \"everything is a file\" and \"build flexible, tested, single-function tools.\" If the UNIX philosophy represents a 2D picture, then microservices are a higher dimension: 3D. Rules of Microservices An app that cannot crash. It has a way to fail gracefully but that doesn't involve some downstream coder poking through your call stack. An app that does one and only one useful business function. An app that is composable with other apps from the command line. An app that uses dynamic, free-form, late-bound text streams to talk to other apps. An app that can be reasoned about, modified, or completely replaced by a maintenance programmer many years from now with little or no preparation. The app must have tests. The app must do what the tests say it does. The app cannot do anything that the tests do not cover. These tests exist in a compilation unit separate from the app itself and are in no way coupled to it. When in doubt, think of your compiled app as a pure function running inside a program. That program is a plain, vanilla, default operating system. — Citation But while it was once easy to know what your computer was running by using top or ps and checking logs as raw files, like tail -f /var/log/mycoolapp.log, how is it possible to do that with microservices? How do you debug and monitor and maintain them? The answer is: Logging, Monitoring, and Metrics. Docker fortunately does a very good job of logging for us, and the tools and systems our research group runs are small enough that we don't need advanced monitoring (beyond Slack notifications) and metrics (beyond \"wow our CPU usage has been at 100% for four days now!\"). https://youtu.be/y8OnoxKotPQ Now watch this 3min documentary (and check out the YouTube comments) on Microservices in the real world. Thankfully, the LAMP Platform is not this far gone... or is it? DevOps & Git Length: 55 minutes How do we release software, such as the LAMP Platform, or even our own data analysis (such as feature extraction or analysis methods), in such a way that there are no issues to the patient or research experience? How do multiple scientists or developers collaborate on one large project without stepping on each others' toes and causing massive issues? DevOps is the answer. (By the way, this is a great app if you need to use Git on your Mac.) https://www.youtube.com/watch?v=UbtB4sMaaNM DevOps​ ~5 minutes Short for Development Operations, DevOps is essentially a support and management role for software engineers and data scientists. The DevOps pipeline spans from user stories and user experience to ongoing work items and code changes that land in production environments. The DevOps folks abstract away all of the \"hard stuff\" and \"data plumbing\" that you're about to learn to allow engineers and data scientists to focus on their work effectively. What is DevOps? - Amazon Web Services (AWS) If you haven't had much experience working with complex systems or other peoples' code, you might wonder, \"why is this even important?\" This entertaining article describes the pain that you would have naively gone through (and that our research group once upon a time, aka 2018, did go through). Infrastructure as Code, Part One - CrateDB https://www.youtube.com/watch?v=hwP7WQkmECE&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=15&t=1s Git & GitHub​ ~15 minutes Git is the de facto source code versioning system used by most developers today. All LAMP and Cortex code lives in a Git repository, hosted on GitHub.com. The master branch is the current live code, and \"feature branches\" contain new features, bug fixes, etc. that need to be merged into the master branch after all testing and human code review. Understanding the GitHub flow → Once you've watched the video, try out some basic commands here: Learn Git Branching https://www.youtube.com/watch?v=wpISo9TNjfU GitHub offers a number of other features beyond just basic version control: Repository: Git in the Cloud, but with forking and pull requests Allows anyone in the world to collaborate on software (or anything else!) README.md: What is this repo? Explain that here as simple or as complex as you want. Complex example here. LICENSE.md: The legal aspect of open source. See possible licenses here. SECURITY.md: Explain the responsible disclosure policy for security issues and how to report them. CONTRIBUTING.md: helps others understand how to contribute to the repo. See AMAZING example here. Issue/PR Templates: For standardized bug reporting and pull request code review processes. Pages: website hosting (usually for docs, blogs, and other small things) Wiki: repo-specific Wikis for documentation Issues: track problems and feature requests (and more) per-repo → You'll want to thoroughly understand Issues, and this guide will help you with that. Mastering Issues Milestones: track development sprints and work item progress per-repo Projects: track issues and pull requests across repositories Releases: track important releases and share them with the world safely Actions: automated code actions (see below) Discussions: similar to issues, but more like a per-repo discussion board Insights: security bulletins and collaboration metrics https://www.youtube.com/watch?v=8lGpZkjnkt4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=19&t=3s Fun fact: you don't have to use the GitHub website for everything! There's a command line tool companion to git called gh that can help. Set this up in your Jupyter IDE or local computer. (You don't need to follow this guide right now and actually install/use the gh tool.) Manual For example, once you've pushed some code, you can do gh pr create right in the command line to send off a pull request and assign a reviewer! gh pr create https://www.youtube.com/watch?v=scEDHsr3APg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=17&t=34s DevOps Pipeline​ ~25 minutes Continuous pipelines are the bread and butter of DevOps, automating the entire workflow end-to-end. Remember, the leading cause of problems in code are humans! Automations help simplify and react to code changes or issues dynamically. The pipeline explained in a simple diagram: https://www.youtube.com/watch?v=RYQbmjLgubM Continuous Testing​ → Types of Tests: Unit: Test each individual \"unit\" of code (such as functions or classes within a project). Unit tests explain what a unit of code is supposed to do and should be narrow in scope, without any dependencies on other code. (For example, assert 2 + 2 == 4 is a unit test that confirms the behavior of the + operator.) Snapshot/Interaction: Test the user interface in snapshots as well as through user interaction from one component to another. (This is analogous to unit testing for the frontend. API testing is the same but for the backend.) Integration: Test multiple units of code and how they work together, for example, different dependencies, libraries, or multiple peoples' code being merged together. Regression: Re-test all individual units of code to ensure integration hasn't broken anything in the process. Acceptance: Test to ensure the entire release of the application (or data analysis notebook) works the way the end users expect it to work. Often, this is a manual step performed by a human (the \"release manager\") or others on the team to go through a very detailed checklist of each requirement. (Though there are ways to automate this phase as well!) https://www.youtube.com/watch?v=1er2cjUq1UI Continuous Integration​ https://www.youtube.com/watch?v=2TTU5BB-k9U Continuous Deployment​ We use the terms \"continuous deployment\" and \"continuous delivery\" interchangeably in our team due to our quite small scale (as opposed to massive companies like Apple or Google...). We use several environments with the LAMP Platform: Development: Each individual data scientist or developer will commit changes to code in a local environment and show that it runs correctly and passes all tests before making a pull request to merge it into the master branch. Developers/scientists will perform code review before approving the pull request as well, allowing a pair of human eyes to triple-check everything. Staging: This is the environment built on the master branch where completed features, improvements, and bug fixes are integrated and tested for quality assurance (QA). Production: When staging is QA tested and cleared, a git tag is created (i.e. GitHub Release) on that specific commit in the master branch to indicate that \"this release is ready to go and usable by others!\" When something hits production, it's going to be used by thousands of patients (with or without serious mental illness), and tens to hundreds of clinicians! You should NEVER be pushing faulty code to production, and AVOID testing anything in production if you can! https://www.youtube.com/watch?v=LNLKZ4Rvk8w Now enjoy this meme about developer experience vs. testing in production. You'll start off naively testing in production, then learn enough to know that testing in production is terrible, but then eventually realize that life is too short to concern yourself with that, and then you'll test in production anyways. 🙂 https://www.youtube.com/watch?v=eB0nUzAI7M8&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=18&t=2s GitHub Actions​ ~10 minutes Here you'll see how CI/CD (and testing) is automated in practice across the LAMP Platform and Cortex repositories. You don't need to follow along! An important note is that most CI/CD pipelines involve \"secrets\" — passwords or tokens that allow users to control some kind of tool. For example, an AWS token allows you or a malicious third-party to control ANY AWS service, such as spinning up hundreds of EC2 instances for crypto-mining, causing our team to be charged thousands of dollars. It's important to keep all secrets separate from code and CI/CD pipelines; we do so through Docker Compose environment variables and GitHub repository secrets, which are only visible to our team. If you would like to follow along on the terminal, see the guide below: Work with GitHub Actions in your terminal with GitHub CLI - The GitHub Blog — GoatOps. GoatOps. 🙂 Databases & APIs Length: 80 minutes The three main goals of an application, in our flexible definition, are: Access and manipulate data and perform tasks about the data. Communicate with other tools and services that help it fulfill its role. Externalize itself by allowing clients to speak to it. To achieve these goals, we'll need to databases (#1), message queues (#2), and an API (#3). https://www.youtube.com/watch?v=LxcH6z8TFpI&t=118s Data Lakes & Databases​ ~20 minutes Data Lakes are a term that originated with Big Data, but essentially refer to a massive collection of different data sources acting as one big database. The LAMP Platform database is actually more of a mini data lake with combined feature store support! Read the article below to better understand what feature stores are, and why feature extraction (i.e. through LAMP Cortex) is important. What is a Feature Store? - Tecton https://www.youtube.com/watch?v=W2Z7fbCLSTw&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=27&t=3s There are MANY different kinds of databases that all work with data in different ways; we primarily use key-value databases (which you may also know in Cloud parlance as Object Storage) and document databases (which hold schema-less JSON data). (We'll talk about what \"schema\" means in the data modeling context later on.) https://www.youtube.com/watch?v=eIQh02xuVw4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=41&t=2s While we do not use GraphQL, the LAMP Platform uses a combination of technologies (OpenAPI, JSONSchema, and JSONata) to support what are referred to as document transforms. These document transforms are essentially the same as GraphQL queries. It also integrates support for images, files, and dynamic visualizations using Vega, which you'll learn about in a later module. https://www.youtube.com/watch?v=aOE90VAVOcU While we no longer use CouchDB (as of April 2021), the same principles presented here apply to MongoDB (and AWS DocumentDB, the managed version of MongoDB we use). https://www.youtube.com/watch?v=aj9CDZm0Glc Message Queues​ ~20 minutes Message queues are another incredibly important paradigm for designing robust software, across the healthcare systems spectrum. While the LAMP Platform does not use Apache Kafka, it uses NATS, which operates on the same fundamentals. It's not hard to understand why we want something like this as part of LAMP: \"If a survey is scheduled for 3pm on Friday, send a push notification to the patient's mobile device,\" or \"If a patient scores highly on suicidality, send a notification to their physician immediately.\" Read the below article as well (only until the Arguing Semantics section) to gain a better understanding. The rest of the article is optional if you do want a more comprehensive explanation of specific message queues or Cloud services. The Big Little Guide to Message Queues https://www.youtube.com/watch?v=kG-fLp9BTRo&t=213s APIs & SDKs​ ~40 minutes **Application Programming Interface (API)**s are essentially a set of nouns and verbs that create a vocabulary for a microservice. By documenting and exporting (sharing) your API with others, you enable others to integrate your tools with their tools. For example, to be considered part of the LAMP Platform, a service must speak the \"LAMP Protocol,\" which is an API. **Software Development Kit (SDK)**s are a programming language-specific toolbox for handling an API. For example, the LAMP Platform offers the LAMP-py SDK for Python, the LAMP-r SDK for R, and the LAMP-js SDK for JavaScript/TypeScript. All of these SDKs call through to the exact same API, but take care of housekeeping for you and allow you to call methods on native objects and not think about HTTP network calls, JSON serialization, TLS security and so on. https://www.youtube.com/watch?v=-MTSQjw5DrM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=42&t=62s https://www.youtube.com/watch?v=lsMQRaeKNDk HTTP & REST​ The LAMP Protocol relies on HTTP/2.0 (for transporting data between client and server), TLS/1.3 (for encryption in transit), and JSON (for encoding of data payloads). You do not need to follow along with the NodeJS example in the video, but do realize that this is the exact same setup used by the LAMP Platform's API Server! Across LAMP-supported languages, there are packages to set up your own web server: express for NodeJS flask for Python plumber for R You'll also need to understand how URLs work, as they are part of the HTTP standard: How URLs work? Enjoy this 20+ year old easter egg in the HTTP standard: https://www.youtube.com/watch?v=pRS9LRBgjYg OpenAPI & JSONSchema​ There's no point to an API if no one understands how to use it — or worse, if it can't be tested and maintained. OpenAPI allows you to do just that by documenting APIs, and even more, like automatically generating SDKs! JSONSchema is one part of that, allowing you to document specifically JSON objects. The LAMP Platform uses JSONSchema for its *Spec data types, allowing the dashboard to automatically understand, configure, and work with any kind of Activity, Sensor, or Tag. (You'll learn more about this in the LAMP documentation.) Understanding JSON Schema - Understanding JSON Schema 7.0 documentation https://www.youtube.com/watch?v=UBUNrFtufWo&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=32&t=3s Authentication & Authorization​ Authentication refers to the process of understanding \"who you are,\" and authorization is the process of understanding \"what you can do.\" They're both required and interlinked, but authentication is a handshake process that happens between the client and server. Once the client authenticates, the server will already know what possible actions the client can take. There are three main ways to support authentication in an HTTP-based API: Session: uses browser cookies and saves session data on the server; requires specific login and logout functions to start and stop a session. If the password is changed, the server can auto-logout the browser session. Basic Tokens: a simple username-and-password combination; VERY insecure UNLESS using HTTPS, which encrypts this data. If the password is changed, API calls using the old password will fail. Bearer Tokens: the server generates a token representing an authorized user, with specific parameters and an expiration. If the password is changed, it is incredibly difficult to handle. The only way of doing so is to keep track of a list of disabled tokens until their expiry date has passed. Another concept is API Tokens, which we will not cover here, but are essentially a \"password\" that identifies which client code is calling the API. For example, \"John requests Patient X data using Dashboard\" vs. \"John requests Patient X data using MyCoolApp.\" This is helpful to understand usage patterns and disable bad actors from abusing an API. Pandas & Vega Length: 150 minutes In our field of research, building and orchestrating applications is just the first phase. It's important to discuss now how clients (ourselves, technically) use what we have established in the last several modules to understand, manipulate, and visualize data in an effective and contextual way. This is true across R, Python, and Javascript/Typescript. Also, there's some important housekeeping lessons to be used for R and Python, such as package management. 💡 This module expects you have experience with either Python/Pandas or R/Tidyverse. If you do not, please complete the tutorial(s) below. While R is a supported language, our lab prefers and primarily only uses Python for data analysis. If you are transitioning from R to Python, try the tutorial(s) below. Learning Python: From Zero to Hero → The following are reference guides only and do not need to be followed line-by-line: Python, Statistical Computing in Python, and R script. They are useful if you need to brush up on Python/R or already have programming experience and just need to look something up quickly. Below is another quick reference guide to many basic and advanced Python operations. gto76/python-cheatsheet Data Frames​ ~80 min Data frames are the most essential data structure used across statistical and scientific computing. You can think of them as an Excel spreadsheet or CSV file, for the most part, but with Python functions and operators to help you mold and manipulate data easily. 10 minutes to pandas - pandas 1.2.4 documentation From this User Guide, complete the following chapters: 10 minutes to pandas Intro to data structures Essential basic functionality Indexing and selecting data Merge, join, concatenate and compare Windowing Operations Time series / date functionality Time deltas Frequently Asked Questions Cookbook You MUST read and understand this guide below as well! Pandas and NumPy allow you to operate on extremely large data sets efficiently using vectorized operations but it is up to the user (you!) to structure your analysis code correctly. It really does make the difference between 15 days and 15 minutes for data processing. A Beginner's Guide to Optimizing Pandas Code for Speed Read the article below as well to get a better understanding for why NumPy is so fast — faster than raw C in some cases (when using numexpr)! NumPy/Pandas Speed https://www.youtube.com/watch?v=AAuPPorsmJc&t=109s Altair for Visualization​ ~40 min To those familiar with ggplot2 in R, Altair should be quite familiar as it also implements the same \"grammar of graphics.\" To those familiar with matplotlib or seaborn in Python, forget what you know and start fresh! An article representation of these few videos is also available: Understanding The Altair Stack → Once you've watched the video (and/or read the article above), try following along to this getting started guide. Basic Statistical Visualization - Altair 4.1.0 documentation https://www.youtube.com/watch?v=U7w1XumKK60 Once you've watched this video, working with Altair may look a little bit complex. Rest assured, it is by far the simplest visualization library to use. Skim through this article showing code examples across different Python libraries for different types of visualizations: A Dramatic Tour through Python's Data Visualization Landscape (including ggplot and Altair) → For a more in depth understanding (optional), check out this guide-book from the team that built Vega/Altair. To learn how to use UpSetR plots in Altair, see the example code here. https://www.youtube.com/watch?v=LSEPyCqjoAg&t=108s Now open the Vega live editor and tap the [Examples] button in the top toolbar to play with some sample visualizations. Note that all Vega/Altair visualizations can be interactive and embedded into the LAMP Platform user interfaces or generate static PNG/SVG files. Editor/IDE for Vega and Vega-Lite Example Gallery - Altair 4.1.0 documentation https://www.youtube.com/watch?v=FSs_JYwnAdI&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=6&t=10s Programming Language Internals​ While you write code at a very superficial level, there's a lot that goes on behind the scenes, from managing threads on your CPU's many cores to managing heap and stack allocations on system memory (RAM). This video approaches the concept from the perspective of Javascript, but everything here is true of any interpreted language, including Javascript/Typescript, Python, and (especially) R. While there is mention of prototype-based inheritance, this is largely JS-specific, and most other languages have the familiar model of classes → objects. R as a statistics scripting language surprisingly has several implementations of class-based inheritance, such as S3, S4, and R6, which is preferred. Python supports non-blocking async I/O event loops through the asyncio built-in library, and R supports the same through several libraries. Online Algorithms​ ~10 minutes As a minor note, it's important to understand that the kind of data analysis we do, primarily operating on extremely large quantities of time series data, requires a different approach than you may be used to for smaller data sets that may have been able to fit into Excel. Since there's simply no possible way for any the terabytes of LAMP data to fit in system memory, let alone an Excel sheet, we turn to a category of algorithms called Online Algorithms. Read the article below to better understand what they are and why we need them. Data Streams and Online Machine Learning in Python Package Managers​ ~10 minutes When working with JavaScript or TypeScript, the default package manager, npm (Node Package Manager) handles a lot of dependency management and development script workflow for you, avoiding what's called \"dependency hell\". In Python, be sure that all packages use the Poetry package manager. (In R, be sure that all packages use the **Packrat** package manager.) The tutorial/guide below will explain why a package manager is critical and how to set up and begin using Poetry. A Poetic Apology Cell 0 # First, define a function that performs your API call or download. def my_big_scary_download(): # TODO: Download 5 TB of data from somewhere like LAMP. pass Cell 1 # Next, check if the cached pickle exists and load it. # If not, run the download/API call function and then cache it. import pickle try: df = pickle.load(open(\"_cache.pickle\", \"rb\")) except (OSError, IOError) as e: df = my_big_scary_download() pickle.dump(df, open(\"_cache.pickle\", \"wb\")) Cell 2 # Now use the df like any other python variable! df.head() Python Pickles​ 🔥 AVOID DUMPING DATA TO CSV FILES AT ALL COST! This is a highly inefficient and expensive process (if on AWS like we are, for example). When performing data analysis on a LARGE quantity of data, either from the LAMP Platform or some other network resource that requires downloading of data, it's bad practice to re-download the same data each and every time your analysis code raises a SyntaxError or some other silly exception. Instead, use pickles in your Jupyter notebooks to effectively cache and uncache data! 💡 By using two cells like the ones at the left here in all of your Jupyter notebooks, you allow your notebook to work in isolation AND be completely portable. (Meaning, others are able to understand where the data came from and save the cache on their computers too.) If you're curious how much better Pickles are, check this comparison out, and also keep in mind that Pickles are native to Python and can embed billions of arbitrary objects into one file, where in contrast for CSV files, you'll need to write custom code for managing thousands of files. → Original Source Article → Two concerns are left as exercises for the reader to complete someday: A python function to delete the cached pickle file to re-download everything. A python function to progressively append to the existing pickle instead of deleting and re-downloading data. TypeScript & React Length: 100 minutes While Python or R make sense for data analysis and scientific/statistical computing, it's not possible to build a website or app user interface in those languages. And while Python allows you to build backend systems, it may not be the best choice in some cases. This is where TypeScript and React come in — one unified language for all frontend and backend development. From patient and clinician dashboards, to automated gift card scripts, to cognitive tests, almost everything non-analysis in our research group is written in TypeScript. 💡 This module expects you have BASIC experience with Python or a similar programming language. If you do not, please complete the tutorial below. The exercises in this module are OPTIONAL if you are not going to be working on interactive data visualization, etc. Please still watch the videos! Learning Python: From Zero to Hero https://www.youtube.com/watch?v=9emXNzqCKyg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=7&t=10s TypeScript​ ~45 minutes Before we can begin talking about TypeScript, let's begin with a refresher on JavaScript basics. If you'd like a more in-depth written tutorial, the one below will help. (Additionally, Mozilla Developer Network hosts the official/best JS documentation available on the internet.) JavaScript Guide One major difference between JS and other similar languages (like Python) is the existence of the undefined keyword in addition to null (or None in Python, and NULL in R, but R also has the NA keyword which is similar). undefined vs. null revisited https://www.youtube.com/watch?v=ahCwqrYpIuM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=3&t=35s TypeScript is an incremental superset of JavaScript that resolves a significant number of concerns with JS, including the most basic annoyances that cause significant bugs, like 1 == '1' (in JS, string 1 equals number 1, which is horrifying!). For these reasons, we strongly prefer using TypeScript instead of JavaScript dirctly. Documentation - TypeScript for JavaScript Programmers https://www.youtube.com/watch?v=fsVL_xrYO0w&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=4&t=17s Object-oriented and functional programming (aka lambda programming) are two ways to solve problems (which you can find across JS, TS, Python, and R!). The principles of functional programming are: pure functions that do not manipulate state AND immutable data. You'll see these concepts come up in both the context of data analysis but also in the next sections about React for user interface programming. https://www.youtube.com/watch?v=Tn6-PIqc4UM&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=28&t=4s React​ ~20 minutes Most of the time, user interfaces are built using imperative programming: instantiate some objects that represent visual elements on the screen, when something changes, update properties on those objects, and at the same time, register callbacks on those objects to know when the user does something like press a button or type some text. React, however, flips that on its head through the declarative programming paradigm. With React, you describe what the user interface should look like in a pure function (a component) and React will help you reconcile the changes. Once you've finished watching the video, the article below will help you understand how to think differently when working with React — which is, believe it or not, the critical difference between your patient dashboard loading in 15 minutes vs. 15 seconds. Thinking in React - React Before we go further, let's talk about what makes up a \"bare\" HTML page. That is, some individual my_cool_site.html that would run in the browser on its own without any extra effort! My current HTML boilerplate At its core, the simplest HTML file would look like this! [expand to view] My Cool Website!

    Hello World!

    https://www.youtube.com/watch?v=5IG4UmULyoA&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=31&t=1s Once upon a time, back when \"Web 2.0\" was still a thing, all you needed was HTML, CSS, and JS to spin up a website. Things are different today, with a number of steps (resembling the old \"compiling and linking\" of programming languages like C++) between your writing of code and the deployment of your website or app. While writing backend code in TypeScript using NodeJS is fairly simple, frontend development today is significantly more complicated — but at least the pain can be automated away! Luckily, React automates all of the Webpack setup (create-react-app and react-scripts) so most of the suffering you'll witness in this video is not something you or others have to do manually. If you're not building a web application and just need a lean web site in a single HTML file, consider using SkyPack instead! This simplifies what would have been a tremendous amount of effort! Skypack + CodePen - CodePen Blog At its core, the simplest HTML file using React/JSX (and also Material-UI) would look like this! [expand to view]
    https://www.youtube.com/watch?v=sFsRylCQblw&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=34&t=19s Progressive Web Apps​ ~20 minutes ⚠️ Watch the video until 2:03 ONLY. While you might think of websites as pretty static pieces of content, today there are a number of features that are accessible entirely from the web browser. This is called a Progressive Web App (PWA, or \"browser app\"), and the LAMP dashboard, for example, can be installed as am offline-capable browser app with no side effects (except missing out on all sensor data collection of course). The example below is a meditation app that can be installed on your phone but runs entirely in your mobile browser! Calmaria - Focus / Breathe / Relax https://www.youtube.com/watch?v=ppwagkhrZJs&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=35&t=7s So now we know that websites can be installed as apps, and sometimes even work offline, but what features can you tap into? Once you've finished watching the video, on your mobile device, open the page below to see how many crazy things are possible entirely from a browser today. permission.site https://www.youtube.com/watch?v=Qhaz36TZG5Y&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=47&t=29s CSS Layout & Animations​ ~15 minutes While we won't be going over the basics of CSS, the language we use to impart styles and layouts and colors and more to a website (or app!), it's important to know how powerful CSS is. If you don't understand some of what's going on in the second half of the video, that's okay! Especially when used together with React, you can design and develop almost any 2D user interface rapidly. We use the Material-UI framework in our code, a toolbox that abstracts some of these things away so we can think about UI in terms of buttons and dialogs and text fields and so on. 💡 It's important to learn how to use the DevTools (Inspector) in your browser to diagnose missing or broken user interface elements, but this is an exercise left for the reader. 😄 https://www.youtube.com/watch?v=K74l26pE4YA&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=14&t=3s https://www.youtube.com/watch?v=uuOXPWCh-6o&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=16&t=2s https://www.youtube.com/watch?v=HZHHBwzmJLk&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=22&t=28s Code Etiquette & Review Length: 80 minutes At the most fundamental level beyond the infrastructure or packages or libraries that make up the software or analysis notebook you're working on, are the problems you will stumble into while writing code. It's important to understand this set of principles from debugging code to writing better code to reviewing others' code. https://www.youtube.com/watch?v=4Zc9ci9L5wY&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=33&t=20s Describing & Debugging Code​ ~20 minutes It's important to know how to describe what your code is doing. For example, one way to describe something Cortex does is \"it saves the data after you compute the feature functions that follow the same rules for a long time\" and a more accurate way of summarizing that is \"it provides an abstraction to memoize idempotent features.\" https://www.youtube.com/watch?v=UFc-RPbq8kg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=20&t=1s Learning how to solve problems is just as important as solving the problems. You can ignore most of the problem-specific terms and tools being used in this video, but be sure to follow along with the thought process and the idea of using automation code to solve problems, even if that code will only ever be used once. Approaching software problems from first principles https://www.youtube.com/watch?v=kt0bfw4YkFk&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=1 Code Etiquette​ ~40 minutes Care and attention should be applied when writing code; it's not just you who will read and use it, after all. Other humans need to understand it and debug it as well, and good code etiquette starts with good comments! Read the articles below after the short video. Some articles focus on specific tools or programming languages to explain the concepts they're discussing; you can ignore the specifics and focus on the abstract. 💡 Remember, the best code is simple, readable, and reusable, even if it takes longer to perform its task. Optimize For Simplicity First - Qvault god of frontend - god of frontend Technical Debt​ There are particular issues with research software, and some wonder how data analysis code or notebooks get to that terrible unfortunate point where it becomes easier to throw out a previous team member's analysis and re-write it all from scratch. The answer is technical debt (and poor code etiquette, along with emphasis on \"I just need to publish my paper, the code doesn't matter\"). The Shape of Code The True Meaning of Technical Debt 💸 Things You Should Never Do, Part I Misc. Principles of Good Code​ These are small miscellaneous but important things that make for better code. You've only added two lines - why did that take two days! Ship Small Diffs And of course, use the code you've written yourself FIRST, before telling others they can/should/need to use it. Eating your own dog food - Wikipedia Code Reviews​ When your teammates create a pull request, it's the whole team's responsibility to ensure that the code is of high quality and delivers value. Learning how to do effective code reviews makes for a better scientist/developer and for better code. Think of it as the publication peer review process but internal to your team. 8 Tips for Great Code Reviews https://www.freecodecamp.org/news/a-zen-manifesto-for-effective-code-reviews-e30b5c95204a/ https://www.youtube.com/watch?v=g2o22C3CRfU&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=11&t=1s Big Data Analysis​ ~10 minutes These are quite minor conceptual explanations of things that you should be aware of when working with large datasets. Algorithmic Analysis​ When doing any kind of data analysis, understanding the time and performance complexity of the operation being executed is critical. Big O notation allows you to measure that in an abstract way. https://www.youtube.com/watch?v=DC471a9qrU4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=10&t=37s https://www.youtube.com/watch?v=tVCYa_bnITg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=12&t=2s Functional Map-Reduce​ While these two videos show you how to use the functional programming paradigms map() and reduce() on simple arrays in Javascript, these core concepts apply exactly the same whether running on a small array or a petabytes-large database in the cloud. Google realized this and developed MapReduce, and the below example shows how the task of counting word occurrences in a body of literature could be processed in this framework. (For a simple array, splitting is part of the mapping process, and shuffling is part of the reducing process.) → To learn more about Apache Spark or Hadoop/MapReduce, read this article. https://www.youtube.com/watch?v=RvYYCGs45L4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=13&t=2s Asynchronous Functions​ Both Python and Javascript support asynchronous functions to enable concurrent execution of tasks. This is different than parallel execution of tasks, as explained in the diagram below. Programming Fallacies​ ~10 minutes Most of this is fun reading! These articles are quite short and entertaining and will help you understand incorrect assumptions before you even make them. Falsehoods programmers believe about time and time zones Falsehoods Programmers Believe About Names Falsehoods Programmers Believe About Pagination Falsehoods Programmers Believe about REST APIs Fallacies of distributed computing - Wikipedia Team-specific Resources Length: 110 minutes Now that you've covered the entire spectrum of writing code to visualizing data to provisioning resources in the Cloud, the next step is understanding the specific workflows that our team follows. For example, creating repositories, triaging issues, managing releases to the App Stores, and so on. This module is relatively barebones compared to all the prior modules, since you'll now need to learn by putting your knowledge and these resources to practice. Managing Team GitHub Repos​ ~10 minutes Our team GitHub organization houses a LOT of repositories; mostly the LAMP Platform, but some are other projects (or random things like archived old code from ~2017, or the first version of the mindLAMP app...). BIDMC Division of Digital Psychiatry At the organization level, we primarily only create repositories, add team members to the organization, or manage Docker images (explained later). It's important to re-configure security access controls for each member of the organization as team members come and go. The NPM and PyPI tokens (explained later) are configured as GitHub secrets at the organization level. If certain secrets can span across several repositories, it's best to keep them at the organization level instead of repo level. We primarily use team discussions with LAMP Platform development as a message board between our team and the clients/contractors doing the actual development. When creating a new LAMP Platform/Cortex repository at the organization level, ensure the following are configured: Files that MUST be created in the repo: .gitignore configured correctly for the desired programming environment of the repo. [README.md](http://readme.md) with limited contents that points at [docs.lamp.digital](http://docs.lamp.digital) (which is where ALL documentation must go). [LICENSE.md](http://license.md) file with the BSD 3-Clause License. Any project management files, like package.json, package-lock.json, pyproject.toml, or poetry.lock. .github/workflows/* for any GitHub Actions that enable the CI/CD pipeline. Disable Wikis, Issues, Projects, and Discussions: all of these are instead redirected and centralized to the LAMP-platform repository. Configure per-repo security access controls, for example, if an external collaborator only needs push access for LAMP-cortex and NOT the entire LAMP Platform. Configure a Branch Protection Rule for the master branch to: Require pull request reviews before merging When enabled, all commits must be made to a different branch and submitted via a pull request with the required number of approving reviews (one) and no changes requested before it can be merged into the master branch. Dismiss stale pull request approvals when new commits are pushed New reviewable commits pushed to master will dismiss pull request review approvals. Require status checks to pass before merging Choose which status checks must pass before branches can be merged into the master branch. When enabled, commits must first be pushed to another branch, then merged into master after status checks have passed. Require branches to be up to date before merging This ensures pull requests targeting the master branch have been tested with the latest code. Enforce all configured restrictions above for administrators Restrict who can push to matching branches (to our organization) Enable GitHub Pages if the build output is a website (i.e. something HTML-based). TODO: Talk about good git commit etiquette. Issue/Project Tracking​ ~10 minutes Specifically for the LAMP Platform, we want to centralize all issues, project tracking, and discussions into the LAMP-platform repository. BIDMCDigitalPsychiatry/LAMP-platform We use the following scheme to manage issues and releases: Work Item: Represents exactly one pull request (having its own branch in one of the platform repos) performing exactly ONE bug fix OR feature request. Issue: Represents exactly ONE work item, and is tracked as a GitHub Issue on the LAMP-platform repo, labeled appropriately with the issue category, type, and specific details about the bug to fix or feature request. These are triaged by how long it's expected to take to complete the work item, how expensive, or how important it is, and so on. There is a GitHub issue template for collaborators to report bugs or request features that will auto-assign a team member to triage the issue. Sprint: Represents two weeks worth of issues (work items) that are triaged by priority. Release: Represents two sprints worth of issues (work items) that constitute a monthly release of each of the components of the LAMP Platform. When creating a release (i.e. on LAMP-server), collect all the pull requests/commits merged since the last release and create a well-formatted summary list of changes. The release version MUST be the current date in the format YYYY.MM.DD (e.g. 2021.6.1). The CI/CD pipeline will take care of the rest! Be sure to post the update to the docs.lamp.digital What's New page, as well as to the community forum (below). Project: Represents the evolving nature of the entire LAMP Platform, encompassing all past and future releases. The GitHub Project board should contain all triaged issues (work items) that are actively important for our team to take care of, but not ones that are not important to us. 🌟 Tip: linking a GitHub issue or PR in one repository from another entirely separate repository allows GitHub to show that in-line with the comments. Using the LAMP Community Forum​ ~5 minutes If you're assisting with triaging issues/working with collaborators, or doing data analysis using the LAMP Platform, be sure to register for an account on the forum here. In case collaborators post questions, it's important we answer them. LAMP Consortium Managing Package Deployment​ ~10 minutes The CI/CD pipelines attached to each GitHub repository through GitHub Actions automate build/test/deploy processes. Code changes made on the master branch via merged pull requests to a particular repository should trigger a \"staging\" deployment. Once a GitHub Release is created (which is actually just a git tag under the hood), a \"production\" deployment should be triggered. Deployments (both staging and production) may need to upload code/etc. to package repositories. Because all submissions to the CRAN repository are required to be emailed to the CRAN staff and undergo a manual human review, we do not deploy R packages. Credentials to the NPM (Javascript) and PyPI (Python) accounts can be found in the Onboarding → Internal Passwords page. Profile of bidmc_digitalpsych npm An organization-wide GitHub Secret also provides the PYPI_TOKEN and NPM_TOKEN for any GitHub Action to use for deployment, so you will not need to manually remember/configure passwords. If a deployment generates a Docker image instead, we do not use DockerHub, and instead use GitHub Packages to host these images. All our team's Docker images can be found here: Build software better, together → There are no additional credentials for GitHub Packages management (and the GITHUB_TOKEN is provided to any GitHub Actions scripts to push Docker images). iOS & Android App Releases​ ~10 minutes Both the iOS and Android apps must be manually pushed to staging and production with each release cycle. If a code change is made via merged pull request to the iOS app, for example, the GitHub Actions set for that repo will then run. It should automatically build the image and submit it for beta testing. Apple and Google both will send an email to the Team email once processing of this build has completed. At this point, you must log into Apple or Google's app store management console to start beta testing (i.e. \"staging\") or release the beta build (i.e. \"production\"). Credentials for both can be found in the Onboarding → Internal Passwords page. If the App Store review process rejects the build, you will need to respond/follow up and submit a new build via merging a pull request (see step 1). Utility Scripts (& Automations)​ ~5 minutes In addition to actual CI/CD pipelines, our team sometimes uses GitHub Actions for other additional utilities. It's important to double check these scripts once in a while to make sure they're running on schedule with no unexpected results or errors. Instead of setting up the Action to trigger on created release or merged pull request, in these cases we set up the Action to execute on a cron schedule. → For example, the automated RedCap clinical scales importer is a very lightweight Python script that hooks into the LAMP Platform and re-uploads raw RedCap data (which is essentially an Excel file converted to JSON) into the LAMP database. This makes it possible for our team to work with RedCap data directly through the LAMP API or by using Cortex. BIDMCDigitalPsychiatry/clinical-scale-importer Recording Managing Team AWS Services​ ~5 minutes Download this HTML file below and open it in Google Chrome. Plug your credentials in and navigate through us-east-1 and us-east-2 and it will show you every AWS resource billed on our team account! (Some are automatically created by AWS and some are free instead though.) aws_inventory.html → For the LAMP Platform, we essentially stick to these few main services in the us-east-2 (Ohio) region: IAM/Security [required] Billing [required] EC2 (Compute Nodes) node-01 (with 30GB EBS volume) Primarily used for ONLY production LAMP Platform node-02 (with 30GB EBS volume) Primarily used for staging stuff and Jupyter IDEs Watch the video to the left to see how you can access a console for either nodes. This is possible because we enable AWS Session Manager! (If you create new nodes, be sure to do that!) DocumentDB (Database) Currently provisioned for 2x r5.2xlarge nodes, but may need to be scaled back down to one r5.large node. Route53 (Domain Routing) *.lamp.digital domain group: refers to anything LAMP Platform related *.psych.digital domain group: primarily for testing/convenience purposes only *.mapnet.io domain group: specifically for MAPNET use only Any of the other domain groups are for other team projects. S3 Backups/Misc. Stuff CloudFront CDN Currently, [dashboard.lamp.digital](http://dashboard.lamp.digital) is configured to point to the CloudFront distribution. This distribution is configured to point at [db-cdn.lamp.digital](http://db-cdn.lamp.digital) and refresh itself any time index.html changes. Because the React build process creates unique CSS and JS filenames on each re-build, this triggers a full re-cache in CloudFront. Be sure to take a peek and familiarize yourself with what S3 buckets we've provisioned or EC2 instances we've provisioned, etc. An example of what you can do right from the command line through AWS is automating sending emails and text messages! Sending a text message or email via AWS Install & configure AWS CLI​ If running AWS CLI on macOS, use brew install instead of sudo apt-get install. sudo apt-get install awscli && aws configure Send an SMS​ aws sns publish \\ --phone-number \"+1-111-111-1111\" \\ --message \"Hello world!\" Send an Email​ aws ses send-email \\ --from \"john@gmail.com\" \\ --to \"person1@gmail.com person2@gmail.com\" \\ --subject \"My Email Subject\" --text \"My Email Body\" In addition to --to, the --cc and --bcc parameters exist; all of support multiple emails delimited by a single space. In addition to --text, the --html parameter exists, which supports basic HTML tags, inline CSS, but does NOT support https://www.youtube.com/watch?v=5IG4UmULyoA&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=31&t=1s Once upon a time, back when \"Web 2.0\" was still a thing, all you needed was HTML, CSS, and JS to spin up a website. Things are different today, with a number of steps (resembling the old \"compiling and linking\" of programming languages like C++) between your writing of code and the deployment of your website or app. While writing backend code in TypeScript using NodeJS is fairly simple, frontend development today is significantly more complicated — but at least the pain can be automated away! Luckily, React automates all of the Webpack setup (create-react-app and react-scripts) so most of the suffering you'll witness in this video is not something you or others have to do manually. If you're not building a web application and just need a lean web site in a single HTML file, consider using SkyPack instead! This simplifies what would have been a tremendous amount of effort! Skypack + CodePen - CodePen Blog At its core, the simplest HTML file using React/JSX (and also Material-UI) would look like this! [expand to view]
    https://www.youtube.com/watch?v=sFsRylCQblw&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=34&t=19s Progressive Web Apps​ ~20 minutes ⚠️ Watch the video until 2:03 ONLY. While you might think of websites as pretty static pieces of content, today there are a number of features that are accessible entirely from the web browser. This is called a Progressive Web App (PWA, or \"browser app\"), and the LAMP dashboard, for example, can be installed as am offline-capable browser app with no side effects (except missing out on all sensor data collection of course). The example below is a meditation app that can be installed on your phone but runs entirely in your mobile browser! Calmaria - Focus / Breathe / Relax https://www.youtube.com/watch?v=ppwagkhrZJs&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=35&t=7s So now we know that websites can be installed as apps, and sometimes even work offline, but what features can you tap into? Once you've finished watching the video, on your mobile device, open the page below to see how many crazy things are possible entirely from a browser today. permission.site https://www.youtube.com/watch?v=Qhaz36TZG5Y&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=47&t=29s CSS Layout & Animations​ ~15 minutes While we won't be going over the basics of CSS, the language we use to impart styles and layouts and colors and more to a website (or app!), it's important to know how powerful CSS is. If you don't understand some of what's going on in the second half of the video, that's okay! Especially when used together with React, you can design and develop almost any 2D user interface rapidly. We use the Material-UI framework in our code, a toolbox that abstracts some of these things away so we can think about UI in terms of buttons and dialogs and text fields and so on. 💡 It's important to learn how to use the DevTools (Inspector) in your browser to diagnose missing or broken user interface elements, but this is an exercise left for the reader. 😄 https://www.youtube.com/watch?v=K74l26pE4YA&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=14&t=3s https://www.youtube.com/watch?v=uuOXPWCh-6o&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=16&t=2s https://www.youtube.com/watch?v=HZHHBwzmJLk&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=22&t=28s Code Etiquette & Review Length: 80 minutes At the most fundamental level beyond the infrastructure or packages or libraries that make up the software or analysis notebook you're working on, are the problems you will stumble into while writing code. It's important to understand this set of principles from debugging code to writing better code to reviewing others' code. https://www.youtube.com/watch?v=4Zc9ci9L5wY&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=33&t=20s Describing & Debugging Code​ ~20 minutes It's important to know how to describe what your code is doing. For example, one way to describe something Cortex does is \"it saves the data after you compute the feature functions that follow the same rules for a long time\" and a more accurate way of summarizing that is \"it provides an abstraction to memoize idempotent features.\" https://www.youtube.com/watch?v=UFc-RPbq8kg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=20&t=1s Learning how to solve problems is just as important as solving the problems. You can ignore most of the problem-specific terms and tools being used in this video, but be sure to follow along with the thought process and the idea of using automation code to solve problems, even if that code will only ever be used once. Approaching software problems from first principles https://www.youtube.com/watch?v=kt0bfw4YkFk&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=1 Code Etiquette​ ~40 minutes Care and attention should be applied when writing code; it's not just you who will read and use it, after all. Other humans need to understand it and debug it as well, and good code etiquette starts with good comments! Read the articles below after the short video. Some articles focus on specific tools or programming languages to explain the concepts they're discussing; you can ignore the specifics and focus on the abstract. 💡 Remember, the best code is simple, readable, and reusable, even if it takes longer to perform its task. Optimize For Simplicity First - Qvault god of frontend - god of frontend Technical Debt​ There are particular issues with research software, and some wonder how data analysis code or notebooks get to that terrible unfortunate point where it becomes easier to throw out a previous team member's analysis and re-write it all from scratch. The answer is technical debt (and poor code etiquette, along with emphasis on \"I just need to publish my paper, the code doesn't matter\"). The Shape of Code The True Meaning of Technical Debt 💸 Things You Should Never Do, Part I Misc. Principles of Good Code​ These are small miscellaneous but important things that make for better code. You've only added two lines - why did that take two days! Ship Small Diffs And of course, use the code you've written yourself FIRST, before telling others they can/should/need to use it. Eating your own dog food - Wikipedia Code Reviews​ When your teammates create a pull request, it's the whole team's responsibility to ensure that the code is of high quality and delivers value. Learning how to do effective code reviews makes for a better scientist/developer and for better code. Think of it as the publication peer review process but internal to your team. 8 Tips for Great Code Reviews https://www.freecodecamp.org/news/a-zen-manifesto-for-effective-code-reviews-e30b5c95204a/ https://www.youtube.com/watch?v=g2o22C3CRfU&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=11&t=1s Big Data Analysis​ ~10 minutes These are quite minor conceptual explanations of things that you should be aware of when working with large datasets. Algorithmic Analysis​ When doing any kind of data analysis, understanding the time and performance complexity of the operation being executed is critical. Big O notation allows you to measure that in an abstract way. https://www.youtube.com/watch?v=DC471a9qrU4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=10&t=37s https://www.youtube.com/watch?v=tVCYa_bnITg&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=12&t=2s Functional Map-Reduce​ While these two videos show you how to use the functional programming paradigms map() and reduce() on simple arrays in Javascript, these core concepts apply exactly the same whether running on a small array or a petabytes-large database in the cloud. Google realized this and developed MapReduce, and the below example shows how the task of counting word occurrences in a body of literature could be processed in this framework. (For a simple array, splitting is part of the mapping process, and shuffling is part of the reducing process.) → To learn more about Apache Spark or Hadoop/MapReduce, read this article. https://www.youtube.com/watch?v=RvYYCGs45L4&list=PLr08WV22QsVihYD7pkWl14ENWgom6mqVb&index=13&t=2s Asynchronous Functions​ Both Python and Javascript support asynchronous functions to enable concurrent execution of tasks. This is different than parallel execution of tasks, as explained in the diagram below. Programming Fallacies​ ~10 minutes Most of this is fun reading! These articles are quite short and entertaining and will help you understand incorrect assumptions before you even make them. Falsehoods programmers believe about time and time zones Falsehoods Programmers Believe About Names Falsehoods Programmers Believe About Pagination Falsehoods Programmers Believe about REST APIs Fallacies of distributed computing - Wikipedia Team-specific Resources Length: 110 minutes Now that you've covered the entire spectrum of writing code to visualizing data to provisioning resources in the Cloud, the next step is understanding the specific workflows that our team follows. For example, creating repositories, triaging issues, managing releases to the App Stores, and so on. This module is relatively barebones compared to all the prior modules, since you'll now need to learn by putting your knowledge and these resources to practice. Managing Team GitHub Repos​ ~10 minutes Our team GitHub organization houses a LOT of repositories; mostly the LAMP Platform, but some are other projects (or random things like archived old code from ~2017, or the first version of the mindLAMP app...). BIDMC Division of Digital Psychiatry At the organization level, we primarily only create repositories, add team members to the organization, or manage Docker images (explained later). It's important to re-configure security access controls for each member of the organization as team members come and go. The NPM and PyPI tokens (explained later) are configured as GitHub secrets at the organization level. If certain secrets can span across several repositories, it's best to keep them at the organization level instead of repo level. We primarily use team discussions with LAMP Platform development as a message board between our team and the clients/contractors doing the actual development. When creating a new LAMP Platform/Cortex repository at the organization level, ensure the following are configured: Files that MUST be created in the repo: .gitignore configured correctly for the desired programming environment of the repo. [README.md](http://readme.md) with limited contents that points at [docs.lamp.digital](http://docs.lamp.digital) (which is where ALL documentation must go). [LICENSE.md](http://license.md) file with the BSD 3-Clause License. Any project management files, like package.json, package-lock.json, pyproject.toml, or poetry.lock. .github/workflows/* for any GitHub Actions that enable the CI/CD pipeline. Disable Wikis, Issues, Projects, and Discussions: all of these are instead redirected and centralized to the LAMP-platform repository. Configure per-repo security access controls, for example, if an external collaborator only needs push access for LAMP-cortex and NOT the entire LAMP Platform. Configure a Branch Protection Rule for the master branch to: Require pull request reviews before merging When enabled, all commits must be made to a different branch and submitted via a pull request with the required number of approving reviews (one) and no changes requested before it can be merged into the master branch. Dismiss stale pull request approvals when new commits are pushed New reviewable commits pushed to master will dismiss pull request review approvals. Require status checks to pass before merging Choose which status checks must pass before branches can be merged into the master branch. When enabled, commits must first be pushed to another branch, then merged into master after status checks have passed. Require branches to be up to date before merging This ensures pull requests targeting the master branch have been tested with the latest code. Enforce all configured restrictions above for administrators Restrict who can push to matching branches (to our organization) Enable GitHub Pages if the build output is a website (i.e. something HTML-based). TODO: Talk about good git commit etiquette. Issue/Project Tracking​ ~10 minutes Specifically for the LAMP Platform, we want to centralize all issues, project tracking, and discussions into the LAMP-platform repository. BIDMCDigitalPsychiatry/LAMP-platform We use the following scheme to manage issues and releases: Work Item: Represents exactly one pull request (having its own branch in one of the platform repos) performing exactly ONE bug fix OR feature request. Issue: Represents exactly ONE work item, and is tracked as a GitHub Issue on the LAMP-platform repo, labeled appropriately with the issue category, type, and specific details about the bug to fix or feature request. These are triaged by how long it's expected to take to complete the work item, how expensive, or how important it is, and so on. There is a GitHub issue template for collaborators to report bugs or request features that will auto-assign a team member to triage the issue. Sprint: Represents two weeks worth of issues (work items) that are triaged by priority. Release: Represents two sprints worth of issues (work items) that constitute a monthly release of each of the components of the LAMP Platform. When creating a release (i.e. on LAMP-server), collect all the pull requests/commits merged since the last release and create a well-formatted summary list of changes. The release version MUST be the current date in the format YYYY.MM.DD (e.g. 2021.6.1). The CI/CD pipeline will take care of the rest! Be sure to post the update to the docs.lamp.digital What's New page, as well as to the community forum (below). Project: Represents the evolving nature of the entire LAMP Platform, encompassing all past and future releases. The GitHub Project board should contain all triaged issues (work items) that are actively important for our team to take care of, but not ones that are not important to us. 🌟 Tip: linking a GitHub issue or PR in one repository from another entirely separate repository allows GitHub to show that in-line with the comments. Using the LAMP Community Forum​ ~5 minutes If you're assisting with triaging issues/working with collaborators, or doing data analysis using the LAMP Platform, be sure to register for an account on the forum here. In case collaborators post questions, it's important we answer them. LAMP Consortium Managing Package Deployment​ ~10 minutes The CI/CD pipelines attached to each GitHub repository through GitHub Actions automate build/test/deploy processes. Code changes made on the master branch via merged pull requests to a particular repository should trigger a \"staging\" deployment. Once a GitHub Release is created (which is actually just a git tag under the hood), a \"production\" deployment should be triggered. Deployments (both staging and production) may need to upload code/etc. to package repositories. Because all submissions to the CRAN repository are required to be emailed to the CRAN staff and undergo a manual human review, we do not deploy R packages. Credentials to the NPM (Javascript) and PyPI (Python) accounts can be found in the Onboarding → Internal Passwords page. Profile of bidmc_digitalpsych npm An organization-wide GitHub Secret also provides the PYPI_TOKEN and NPM_TOKEN for any GitHub Action to use for deployment, so you will not need to manually remember/configure passwords. If a deployment generates a Docker image instead, we do not use DockerHub, and instead use GitHub Packages to host these images. All our team's Docker images can be found here: Build software better, together → There are no additional credentials for GitHub Packages management (and the GITHUB_TOKEN is provided to any GitHub Actions scripts to push Docker images). iOS & Android App Releases​ ~10 minutes Both the iOS and Android apps must be manually pushed to staging and production with each release cycle. If a code change is made via merged pull request to the iOS app, for example, the GitHub Actions set for that repo will then run. It should automatically build the image and submit it for beta testing. Apple and Google both will send an email to the Team email once processing of this build has completed. At this point, you must log into Apple or Google's app store management console to start beta testing (i.e. \"staging\") or release the beta build (i.e. \"production\"). Credentials for both can be found in the Onboarding → Internal Passwords page. If the App Store review process rejects the build, you will need to respond/follow up and submit a new build via merging a pull request (see step 1). Utility Scripts (& Automations)​ ~5 minutes In addition to actual CI/CD pipelines, our team sometimes uses GitHub Actions for other additional utilities. It's important to double check these scripts once in a while to make sure they're running on schedule with no unexpected results or errors. Instead of setting up the Action to trigger on created release or merged pull request, in these cases we set up the Action to execute on a cron schedule. → For example, the automated RedCap clinical scales importer is a very lightweight Python script that hooks into the LAMP Platform and re-uploads raw RedCap data (which is essentially an Excel file converted to JSON) into the LAMP database. This makes it possible for our team to work with RedCap data directly through the LAMP API or by using Cortex. BIDMCDigitalPsychiatry/clinical-scale-importer Recording Managing Team AWS Services​ ~5 minutes Download this HTML file below and open it in Google Chrome. Plug your credentials in and navigate through us-east-1 and us-east-2 and it will show you every AWS resource billed on our team account! (Some are automatically created by AWS and some are free instead though.) aws_inventory.html → For the LAMP Platform, we essentially stick to these few main services in the us-east-2 (Ohio) region: IAM/Security [required] Billing [required] EC2 (Compute Nodes) node-01 (with 30GB EBS volume) Primarily used for ONLY production LAMP Platform node-02 (with 30GB EBS volume) Primarily used for staging stuff and Jupyter IDEs Watch the video to the left to see how you can access a console for either nodes. This is possible because we enable AWS Session Manager! (If you create new nodes, be sure to do that!) DocumentDB (Database) Currently provisioned for 2x r5.2xlarge nodes, but may need to be scaled back down to one r5.large node. Route53 (Domain Routing) *.lamp.digital domain group: refers to anything LAMP Platform related *.psych.digital domain group: primarily for testing/convenience purposes only *.mapnet.io domain group: specifically for MAPNET use only Any of the other domain groups are for other team projects. S3 Backups/Misc. Stuff CloudFront CDN Currently, [dashboard.lamp.digital](http://dashboard.lamp.digital) is configured to point to the CloudFront distribution. This distribution is configured to point at [db-cdn.lamp.digital](http://db-cdn.lamp.digital) and refresh itself any time index.html changes. Because the React build process creates unique CSS and JS filenames on each re-build, this triggers a full re-cache in CloudFront. Be sure to take a peek and familiarize yourself with what S3 buckets we've provisioned or EC2 instances we've provisioned, etc. An example of what you can do right from the command line through AWS is automating sending emails and text messages! Sending a text message or email via AWS Install & configure AWS CLI​ If running AWS CLI on macOS, use brew install instead of sudo apt-get install. sudo apt-get install awscli && aws configure Send an SMS​ aws sns publish \\ --phone-number \"+1-111-111-1111\" \\ --message \"Hello world!\" Send an Email​ aws ses send-email \\ --from \"john@gmail.com\" \\ --to \"person1@gmail.com person2@gmail.com\" \\ --subject \"My Email Subject\" --text \"My Email Body\" In addition to --to, the --cc and --bcc parameters exist; all of support multiple emails delimited by a single space. In addition to --text, the --html parameter exists, which supports basic HTML tags, inline CSS, but does NOT support - - + +

    Search the documentation

    diff --git a/start_here/accessing_account/index.html b/start_here/accessing_account/index.html index d89eb32d3e..4fafa38fc5 100644 --- a/start_here/accessing_account/index.html +++ b/start_here/accessing_account/index.html @@ -10,8 +10,8 @@ - - + + +

    If no domain was specified by your IT systems administrator, you can leave that field blank ("lamp.my_organization.org" is only for this example).

    \ No newline at end of file diff --git a/start_here/activities/activities/index.html b/start_here/activities/activities/index.html index b2ca184b0c..47a8abcff0 100644 --- a/start_here/activities/activities/index.html +++ b/start_here/activities/activities/index.html @@ -10,8 +10,8 @@ - - + +
    +

    \ No newline at end of file diff --git a/start_here/activities/assets/VinfenTips/index.html b/start_here/activities/assets/VinfenTips/index.html index ea9e4e346c..14ce8eae96 100644 --- a/start_here/activities/assets/VinfenTips/index.html +++ b/start_here/activities/assets/VinfenTips/index.html @@ -10,8 +10,8 @@ - - + +
    +

    Category: EBP – CBT - Skills Training / Relapse Reduction | © Vinfen 2020

    \ No newline at end of file diff --git a/start_here/activities/complete_activities/index.html b/start_here/activities/complete_activities/index.html index d334f4c0d3..e2ba1d9881 100644 --- a/start_here/activities/complete_activities/index.html +++ b/start_here/activities/complete_activities/index.html @@ -10,8 +10,8 @@ - - + +

    Take Surveys and Complete Activities

    @@ -33,6 +33,6 @@

    Streak popups can be customized in that they can be turned on or off for activities. Within groups, each activity can have their own streak. The streak title and description can also be changed by editing the respective "Streak title" and "Streak Description" fields shown below.

    -

    +

    \ No newline at end of file diff --git a/start_here/activities/create_activities/index.html b/start_here/activities/create_activities/index.html index 26393559ff..8556d1c2e7 100644 --- a/start_here/activities/create_activities/index.html +++ b/start_here/activities/create_activities/index.html @@ -10,8 +10,8 @@ - - + +

    Create and Customize Activities

    @@ -39,6 +39,6 @@

    Customize Which Tab an Activity Appears in

    There are four tab options to choose from: Assess, Learn, Manage, and Portal. Check off the box next to the desired tab you would like the activity to appear in.

    Note that you can select no tabs, which hides the activity. This can be helpful if there are schedules assigned to a particular activity. It can also be helpful if there are several surveys grouped together, and you only would like the group to appear. Note that you can also display the activity on multiple tabs.

    -

    Finally, click the "Save" button on the bottom right.

    +

    Finally, click the "Save" button on the bottom right.

    \ No newline at end of file diff --git a/start_here/activities/create_surveys/index.html b/start_here/activities/create_surveys/index.html index a4e10d844e..c773ff2ff6 100644 --- a/start_here/activities/create_surveys/index.html +++ b/start_here/activities/create_surveys/index.html @@ -10,8 +10,8 @@ - - + +
    +
    \ No newline at end of file diff --git a/start_here/activities/create_tips/index.html b/start_here/activities/create_tips/index.html index 124966b124..8bd14cd0c0 100644 --- a/start_here/activities/create_tips/index.html +++ b/start_here/activities/create_tips/index.html @@ -10,8 +10,8 @@ - - + +

    Create and Customize Tips

    @@ -61,6 +61,6 @@

    Embedding Me

    Sample text here...


    ---

    ## Links & Media

    [link text](http://dev.nodeca.com)

    [link with title](http://nodeca.github.io/pica/demo/ "title text!")

    ![image](https://www.flaticon.com/svg/static/icons/svg/3823/3823851.svg)

    <details>
    <summary>Ready to watch a video?</summary>
    <iframe width="400" height="300" src="https://www.youtube.com/embed/NkCPCFGxxr8" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
    </details>

    <details>
    <summary>Ready to read a book?</summary>
    <embed src="data:application/pdf;base64,JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KL091dGxpbmVzIDIgMCBSDQovUGFnZXMgMyAwIFINCj4+DQplbmRvYmoNCg0KMiAwIG9iag0KPDwNCi9UeXBlIC9PdXRsaW5lcw0KL0NvdW50IDANCj4+DQplbmRvYmoNCg0KMyAwIG9iag0KPDwNCi9UeXBlIC9QYWdlcw0KL0NvdW50IDINCi9LaWRzIFsgNCAwIFIgNiAwIFIgXSANCj4+DQplbmRvYmoNCg0KNCAwIG9iag0KPDwNCi9UeXBlIC9QYWdlDQovUGFyZW50IDMgMCBSDQovUmVzb3VyY2VzIDw8DQovRm9udCA8PA0KL0YxIDkgMCBSIA0KPj4NCi9Qcm9jU2V0IDggMCBSDQo+Pg0KL01lZGlhQm94IFswIDAgNjEyLjAwMDAgNzkyLjAwMDBdDQovQ29udGVudHMgNSAwIFINCj4+DQplbmRvYmoNCg0KNSAwIG9iag0KPDwgL0xlbmd0aCAxMDc0ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBBIFNpbXBsZSBQREYgRmlsZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIFRoaXMgaXMgYSBzbWFsbCBkZW1vbnN0cmF0aW9uIC5wZGYgZmlsZSAtICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjY0LjcwNDAgVGQNCigganVzdCBmb3IgdXNlIGluIHRoZSBWaXJ0dWFsIE1lY2hhbmljcyB0dXRvcmlhbHMuIE1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NTIuNzUyMCBUZA0KKCB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDYyOC44NDgwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjE2Ljg5NjAgVGQNCiggdGV4dC4gQW5kIG1vcmUgdGV4dC4gQm9yaW5nLCB6enp6ei4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjA0Ljk0NDAgVGQNCiggbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDU5Mi45OTIwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNTY5LjA4ODAgVGQNCiggQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA1NTcuMTM2MCBUZA0KKCB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBFdmVuIG1vcmUuIENvbnRpbnVlZCBvbiBwYWdlIDIgLi4uKSBUag0KRVQNCmVuZHN0cmVhbQ0KZW5kb2JqDQoNCjYgMCBvYmoNCjw8DQovVHlwZSAvUGFnZQ0KL1BhcmVudCAzIDAgUg0KL1Jlc291cmNlcyA8PA0KL0ZvbnQgPDwNCi9GMSA5IDAgUiANCj4+DQovUHJvY1NldCA4IDAgUg0KPj4NCi9NZWRpYUJveCBbMCAwIDYxMi4wMDAwIDc5Mi4wMDAwXQ0KL0NvbnRlbnRzIDcgMCBSDQo+Pg0KZW5kb2JqDQoNCjcgMCBvYmoNCjw8IC9MZW5ndGggNjc2ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBTaW1wbGUgUERGIEZpbGUgMiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIC4uLmNvbnRpbnVlZCBmcm9tIHBhZ2UgMS4gWWV0IG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NzYuNjU2MCBUZA0KKCBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY2NC43MDQwIFRkDQooIHRleHQuIE9oLCBob3cgYm9yaW5nIHR5cGluZyB0aGlzIHN0dWZmLiBCdXQgbm90IGFzIGJvcmluZyBhcyB3YXRjaGluZyApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY1Mi43NTIwIFRkDQooIHBhaW50IGRyeS4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NDAuODAwMCBUZA0KKCBCb3JpbmcuICBNb3JlLCBhIGxpdHRsZSBtb3JlIHRleHQuIFRoZSBlbmQsIGFuZCBqdXN0IGFzIHdlbGwuICkgVGoNCkVUDQplbmRzdHJlYW0NCmVuZG9iag0KDQo4IDAgb2JqDQpbL1BERiAvVGV4dF0NCmVuZG9iag0KDQo5IDAgb2JqDQo8PA0KL1R5cGUgL0ZvbnQNCi9TdWJ0eXBlIC9UeXBlMQ0KL05hbWUgL0YxDQovQmFzZUZvbnQgL0hlbHZldGljYQ0KL0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcNCj4+DQplbmRvYmoNCg0KMTAgMCBvYmoNCjw8DQovQ3JlYXRvciAoUmF2ZSBcKGh0dHA6Ly93d3cubmV2cm9uYS5jb20vcmF2ZVwpKQ0KL1Byb2R1Y2VyIChOZXZyb25hIERlc2lnbnMpDQovQ3JlYXRpb25EYXRlIChEOjIwMDYwMzAxMDcyODI2KQ0KPj4NCmVuZG9iag0KDQp4cmVmDQowIDExDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDAwMTkgMDAwMDAgbg0KMDAwMDAwMDA5MyAwMDAwMCBuDQowMDAwMDAwMTQ3IDAwMDAwIG4NCjAwMDAwMDAyMjIgMDAwMDAgbg0KMDAwMDAwMDM5MCAwMDAwMCBuDQowMDAwMDAxNTIyIDAwMDAwIG4NCjAwMDAwMDE2OTAgMDAwMDAgbg0KMDAwMDAwMjQyMyAwMDAwMCBuDQowMDAwMDAyNDU2IDAwMDAwIG4NCjAwMDAwMDI1NzQgMDAwMDAgbg0KDQp0cmFpbGVyDQo8PA0KL1NpemUgMTENCi9Sb290IDEgMCBSDQovSW5mbyAxMCAwIFINCj4+DQoNCnN0YXJ0eHJlZg0KMjcxNA0KJSVFT0YNCg==" width="400" height="520" type="application/pdf">
    </details>

    ## Tables

    | hello | world | this | is | a |
    |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|-------|----------------|----|----------|
    | table | 1 | 2 | 3 | 4 |
    | abc | 123 | | | |
    | ![embedded image](data:image/png;base64,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) | | 1. hi 2. hello | | **test** |
    -

    +
    \ No newline at end of file diff --git a/start_here/activities/customize_activities/index.html b/start_here/activities/customize_activities/index.html index 3884a6ecdc..46aa4ad9a6 100644 --- a/start_here/activities/customize_activities/index.html +++ b/start_here/activities/customize_activities/index.html @@ -10,8 +10,8 @@ - - + +
    +

    How to schedule an activity from the Patient Profile

    \ No newline at end of file diff --git a/start_here/activities/delete_activities/index.html b/start_here/activities/delete_activities/index.html index 374ffdfd11..c6176b3484 100644 --- a/start_here/activities/delete_activities/index.html +++ b/start_here/activities/delete_activities/index.html @@ -10,8 +10,8 @@ - - + + +

    \ No newline at end of file diff --git a/start_here/activities/visualize/index.html b/start_here/activities/visualize/index.html index f44d970f76..30b271f05b 100644 --- a/start_here/activities/visualize/index.html +++ b/start_here/activities/visualize/index.html @@ -10,8 +10,8 @@ - - + +

    Visualize data

    @@ -69,6 +69,6 @@

    If your clinic or study has enabled some sensor types, you'll find them here in this section. As before, tap on an item's bubble to view the graphs for that type of data. You'll see Step Count as an example below.

    -

    +

    \ No newline at end of file diff --git a/start_here/battery_data_usage/index.html b/start_here/battery_data_usage/index.html index db94eabae9..c8dbaf696e 100644 --- a/start_here/battery_data_usage/index.html +++ b/start_here/battery_data_usage/index.html @@ -10,8 +10,8 @@ - - + +
    +
    \ No newline at end of file diff --git a/start_here/care_team/index.html b/start_here/care_team/index.html index 81902a587e..3447b9d604 100644 --- a/start_here/care_team/index.html +++ b/start_here/care_team/index.html @@ -10,8 +10,8 @@ - - + + +

    ...and more.

    \ No newline at end of file diff --git a/start_here/create_patients_participants/index.html b/start_here/create_patients_participants/index.html index 8dd69d29d1..3dec6dae43 100644 --- a/start_here/create_patients_participants/index.html +++ b/start_here/create_patients_participants/index.html @@ -10,8 +10,8 @@ - - + + +

    We recommend the structured JSON export option wherever possible, as the LAMP Platform processes and harmonizes your data automatically for you. Selecting CSV will disable these optimizations and may require you to manually process your data yourself.

    \ No newline at end of file diff --git a/start_here/import_activities/index.html b/start_here/import_activities/index.html index 7a30f91e4a..1ef0a28f75 100644 --- a/start_here/import_activities/index.html +++ b/start_here/import_activities/index.html @@ -10,8 +10,8 @@ - - + + +

    If you’re a clinic administrator and would like to ensure that all the clinics you manage are using the most recent versions of some assessments, this method allows you to quickly synchronize different clinics.

    \ No newline at end of file diff --git a/start_here/instruments/index.html b/start_here/instruments/index.html index 44e82708f1..ce5ed91810 100644 --- a/start_here/instruments/index.html +++ b/start_here/instruments/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/start_here/logging_in/index.html b/start_here/logging_in/index.html index 12bcd25692..ba48d99243 100644 --- a/start_here/logging_in/index.html +++ b/start_here/logging_in/index.html @@ -10,8 +10,8 @@ - - + + +

    \ No newline at end of file diff --git a/start_here/overview/index.html b/start_here/overview/index.html index 7860e8d498..afc1bebf38 100644 --- a/start_here/overview/index.html +++ b/start_here/overview/index.html @@ -10,8 +10,8 @@ - - + + +

    You can customize different studies and groups with sensors, activities, and tips. See Users vs Activities vs Sensors vs Studies Tab for more information about studies and groups.

    \ No newline at end of file diff --git a/start_here/sensors/index.html b/start_here/sensors/index.html index 160e6d27b8..3531587c68 100644 --- a/start_here/sensors/index.html +++ b/start_here/sensors/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/start_here/updates_tutorial/index.html b/start_here/updates_tutorial/index.html index 804a59938c..fa88df33a7 100644 --- a/start_here/updates_tutorial/index.html +++ b/start_here/updates_tutorial/index.html @@ -10,11 +10,11 @@ - - + + +
    \ No newline at end of file diff --git a/start_here/updating_frequency/index.html b/start_here/updating_frequency/index.html index fa8ac8e3c4..8f5a7508ab 100644 --- a/start_here/updating_frequency/index.html +++ b/start_here/updating_frequency/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/start_here/users_vs_activities/index.html b/start_here/users_vs_activities/index.html index 1d5682b8fe..0f9f7233d0 100644 --- a/start_here/users_vs_activities/index.html +++ b/start_here/users_vs_activities/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/start_here/view_dashboard/index.html b/start_here/view_dashboard/index.html index 438b0501ec..5efdabc218 100644 --- a/start_here/view_dashboard/index.html +++ b/start_here/view_dashboard/index.html @@ -10,8 +10,8 @@ - - + + +

    This section of the app is useful to integrate a care team into mindLAMP and enables messaging features between patients and clinicians. This feature is disabled by default.

    \ No newline at end of file diff --git a/start_here/wearables/index.html b/start_here/wearables/index.html index 9a14b957c2..fb9123c855 100644 --- a/start_here/wearables/index.html +++ b/start_here/wearables/index.html @@ -10,8 +10,8 @@ - - + +
    +

    Visualizations are can be displayed on the Prevent tab.

    \ No newline at end of file diff --git a/troubleshooting/index.html b/troubleshooting/index.html index 790be06aa9..dba95b9f6d 100644 --- a/troubleshooting/index.html +++ b/troubleshooting/index.html @@ -10,8 +10,8 @@ - - + +

    Troubleshooting

    @@ -30,6 +30,6 @@

    team@digitalpsych.org

    App Won't Load

    If the app won't load there are two strategies. First, verify the strength of the wifi network you are using, as well as your cell Service. Sometimes the app buffering is simply a result of a poor connection. If there is not an issue with your device connectivity, you can always access the app through the online dashboard.

    -
    +
    \ No newline at end of file diff --git a/using/assess/index.html b/using/assess/index.html index c536ad5781..f8dea0d674 100644 --- a/using/assess/index.html +++ b/using/assess/index.html @@ -10,8 +10,8 @@ - - + +

    A - Assess

    @@ -25,6 +25,6 @@
    JewelsVoice Recording

    The microphone record label and the microphone re-record label can both be changed by clicking the pencil icon and then editing these labels under "Activity Settings". This might be useful if a researcher would like to include specific instructions on the type of content to record or a patient safety disclaimer.

    -

    Sensors function as one mindLAMP's integral features for passive data collection. Sensors are passive data markers that allow the mindLAMp team to create features out of raw passive data. An example of this is using accelerometer, which is detected by the motion of your phone, to create a measure of sleep duration based on when your phone is not moving for an extended period of time at parts of the day. Sensor data collection allows for data analysis to glean insights about how sensor data may be related to active data. If someone was wondering if a patient is experiencing greater depressive symptoms and if that is related to them being at home for longer, a researcher could view the time they may be spending at home based on the GPS data and then look at how their mood scores may reflect changes based on the GPS data. Sensors are added by researchers through the Dashboard and data is obtained through users accepting permissions for the app to access their device's native sensor features (like allowing for mindLAMP to access your location when you open the app for the first time on an iOS device).

    +

    Sensors function as one mindLAMP's integral features for passive data collection. Sensors are passive data markers that allow the mindLAMp team to create features out of raw passive data. An example of this is using accelerometer, which is detected by the motion of your phone, to create a measure of sleep duration based on when your phone is not moving for an extended period of time at parts of the day. Sensor data collection allows for data analysis to glean insights about how sensor data may be related to active data. If someone was wondering if a patient is experiencing greater depressive symptoms and if that is related to them being at home for longer, a researcher could view the time they may be spending at home based on the GPS data and then look at how their mood scores may reflect changes based on the GPS data. Sensors are added by researchers through the Dashboard and data is obtained through users accepting permissions for the app to access their device's native sensor features (like allowing for mindLAMP to access your location when you open the app for the first time on an iOS device).

    \ No newline at end of file diff --git a/using/clin_vs_res/index.html b/using/clin_vs_res/index.html index fc87784a22..b8449f0e28 100644 --- a/using/clin_vs_res/index.html +++ b/using/clin_vs_res/index.html @@ -10,8 +10,8 @@ - - + +

    Clinical vs. Research Use

    @@ -34,6 +34,6 @@

    User ViewsSimple ModeAdvanced Mode

    Why would someone want to use different modes?

    One of mindLAMP's greatest strengths is its flexibility. Many collaborators and users of the opensource app need it for different reasons. Some need to for extremely advanced research purposes, which require complex and intricate use of all of the app's features and beyond, while others may require it for simpler, more clinically accessible uses. While mindLAMP was originally designed for fully research-compatible use, it is evolved to become a platform clinicians can use to present an accessible format for the deliverance of clinical care based on the functionalities the app offers. Sometimes, having so many buttons and abilities right from the start of using the app can be overwhelming, thus highlighting the importance of simpler and neater views. Additionally, security purposes and specific team setups may require that only specific users have access to specific features based on their roles within the team, which is now accounted for by the new administrative user types.

    -

    While transferable between researcher and clinical use, perhaps the greatest potential of this feature is the ability for users to seamlessly transition between research and clinical views, allowing full easy integration of both research and clinical care. You can always create new users with either specialized credentials or overall credentials and you can always transition between Simple and Advanced mode views dependant on what you need it for.

    +

    While transferable between researcher and clinical use, perhaps the greatest potential of this feature is the ability for users to seamlessly transition between research and clinical views, allowing full easy integration of both research and clinical care. You can always create new users with either specialized credentials or overall credentials and you can always transition between Simple and Advanced mode views dependant on what you need it for.

    \ No newline at end of file diff --git a/using/clustering_activities/index.html b/using/clustering_activities/index.html index 251287d281..6349897aed 100644 --- a/using/clustering_activities/index.html +++ b/using/clustering_activities/index.html @@ -10,8 +10,8 @@ - - + + +

    docgrp8

    \ No newline at end of file diff --git a/using/cog_games/index.html b/using/cog_games/index.html index 435076008b..8952a71383 100644 --- a/using/cog_games/index.html +++ b/using/cog_games/index.html @@ -10,8 +10,8 @@ - - + +

    Cognitive Games and Assessments

    @@ -198,6 +198,6 @@

    Customizatio

    Scoring

    Player score is represented by the amount of money held at the end of a 20 spin game.

    Sample Instructions

    -

    "The game presents you with two wheels that can be spun by selecting one of four buttons at the bottom of the screen. The colors of the buttons do not correspond to the colors on the wheel. Each spin can result in a win or loss of money, with the wheel at the top displaying the money you won and the bottom displaying the money lost. The total amount remaining is displayed at the top of the screen. You start with $2000 and have 20 spins per game by default. Points at the end of a session are represented in the amount of money you have."

    +

    "The game presents you with two wheels that can be spun by selecting one of four buttons at the bottom of the screen. The colors of the buttons do not correspond to the colors on the wheel. Each spin can result in a win or loss of money, with the wheel at the top displaying the money you won and the bottom displaying the money lost. The total amount remaining is displayed at the top of the screen. You start with $2000 and have 20 spins per game by default. Points at the end of a session are represented in the amount of money you have."

    \ No newline at end of file diff --git a/using/learn/index.html b/using/learn/index.html index 9e5ddb632f..78fa93e047 100644 --- a/using/learn/index.html +++ b/using/learn/index.html @@ -10,8 +10,8 @@ - - + +

    L - Learn

    @@ -19,6 +19,6 @@

    Tips and resources for patients and study participants are entered by researchers or clinicians through the Dashboard. Notifications for patients and study participants to review tips or resources can be preset and customized to be delivered at any time during the day.

    Clinicians and researchers offer patients and study participants useful health related tips and resources in the Learn tab. These tips can be used for patients and participants to teach themselves about specific topics, refresh their knowledge, or generally explore health-based resources.

    Some examples of what learn tips include are supported snippets of information accompanied by links that explain how to better your physical wellness, your sleep health, understanding that language around mental health providers, and more. It is also possible to enter have videos embedded within the app as well. If requested by a user, a clinician or researcher can also create individualized tips for a patient or participant to learn about. For example, if a patient was specifically struggling with social relationships (i.e. friendships, family dynamics, etc.), a set of tips in the Learn tab could be specifically created from the Dashboard for how to navigate and create healthy social relationships. See example of a resource tip and video tip below:

    -
    Resource TipVideo Tip
    +
    Resource TipVideo Tip
    \ No newline at end of file diff --git a/using/manage/index.html b/using/manage/index.html index ef0923b88a..359f30cab6 100644 --- a/using/manage/index.html +++ b/using/manage/index.html @@ -10,8 +10,8 @@ - - + +

    M - Manage

    @@ -39,6 +39,6 @@

    Collect and save favorite images and quotes to an album. The Hope Box is a digital scrapbook of positive moments.

    Safety Plan (Coming Soon)

    -

    Work with trusted peers or health care team to identify personal signals of anxiety, sadness, or unease and record coping mechanisms.

    +

    Work with trusted peers or health care team to identify personal signals of anxiety, sadness, or unease and record coping mechanisms.

    \ No newline at end of file diff --git a/using/notes_on_android_devices/index.html b/using/notes_on_android_devices/index.html index 89116c0753..e95d9bac84 100644 --- a/using/notes_on_android_devices/index.html +++ b/using/notes_on_android_devices/index.html @@ -10,8 +10,8 @@ - - + + +
    \ No newline at end of file diff --git a/using/prevent/index.html b/using/prevent/index.html index 604021b99f..a099c04945 100644 --- a/using/prevent/index.html +++ b/using/prevent/index.html @@ -10,13 +10,13 @@ - - + +

    P - Prevent

    The prevent tab serves as a way for the the people involved with mindLAMP to view data. mindLAMP collects a combination of active and passive data. Patients and study participants, and clinicians and researchers, can view aggregated data on mindLAMP or on the Dashboard. Data appears in various types of charts and graphs. Data collected from mindLAMP – including survey responses and passive data such as step count – can be viewed through the Prevent tab. See examples in the attached images below.

    As mindLAMP develops, more features created from passive data will be graphed as well. Clinicians can use the prevent tab to have an idea of the clinical implications of a patient's active and passive data and users can view the prevent tab to understand their data and see trends in their activity.

    -

    +

    \ No newline at end of file diff --git a/using/sensors/index.html b/using/sensors/index.html index f2bf9aa32e..86e2f36644 100644 --- a/using/sensors/index.html +++ b/using/sensors/index.html @@ -10,8 +10,8 @@ - - + + +

    The wifi sensor provides information about the devices to which the user's device connects via wifi.

    \ No newline at end of file diff --git a/using/surveys/index.html b/using/surveys/index.html index 62dff26f9c..882ece037b 100644 --- a/using/surveys/index.html +++ b/using/surveys/index.html @@ -10,8 +10,8 @@ - - + +
    + \ No newline at end of file