class: center, middle, inverse, title-slide # Statistics: Rules and Pitfalls ## Biodata Club
### Jessica Minnier, PhD
Assistant Professor of Biostatistics, OHSU-PSU SPH
@datapointier
### March 2, 2018
Slides available at
http://bit.ly/biodata-stats
--- # Topics: ## 1. Big Picture: ["Ten Simple Rules for Effective Statistical Practice"](https://doi.org/10.1371/journal.pcbi.1004961) Kass et al, 2016, PLOS Computational Biology ## 2. Specific Details: ["Common Statistical Pitfalls in Basic Science Research"](http://europepmc.org/articles/PMC5121512) Sullivan et al, 2016, Journal of the American Heart Assocation --- class: center # What is statistics? ### Statistics is not a hurdle to overcome ### It is not a recipe -- ### It is a  framework for doing science  ### It is a  language ("with probability its grammar")  -- ### It informs: ###design + data generation + model + analysis + inference + design next study --- # Rule 1, Methods work *with* the data ### Statistical methods  enable data  to answer scientific Q's - We want to answer a scientific question, not *just* analyze the data because it looks a certain way (method should not be based on just data structure) - Not "Which test should I use?", but "How can the data provide answers?" (statistical test, different type of test, visualization, clustering), i.e. "Where are the differential genes?" -- - Statistical experts are collaborators that + identify potential sources of variability + look for "hidden realities" that might mean the data can't answer your question + then develop analytic goals and strategies - Statistical planning and collaboration needs to start EARLY (see Rule 3) ### Practice Team Science! --- # Example: ### 2 groups, continuous variable; easy, right? - T-test!(?) -- - Not if there's correlation in the data, or confounder(s), or mismeasured outcomes - What if the data are matched and you want to know if the variables move in the same direction/correlate? + T-test is the wrong answer (just estimate correlation!) --- # Variability ### Rule 2: Signals always come with noise - Statisticians are trained to look for and deal with variability - Models simplify patterns to describe variability to be able to detect signal - Big data make these issues worse! -- ### Rule 7: Provide Assessments of Variability - Almost all measurements have uncertainty (estimate it!) - Careful! need to take into account dependencies in data, or else SEs are wrong - Batch effects increase variability - Big data is not a substitute for large `\(n\)` (careful when estimating SE and n) --- # Example: Sample Size ### What's my `\(n\)`? - Sample size/power calculations depend on variability + biological variability + technical variability + sampling variability + but this is often unknown, so consider a range of values - Dependence structure in the data `\(\rightarrow\)` this will change the `\(n\)` + i.e. repeated measures, clustering, family/relatedness, matching --- # Don't Waste Your Money ### Rule 3: Plan Ahead, Really Ahead - Not just "what should my n be?" - Statisticians are trained to look at the big picture and look for future problems in data collection, processing, analysis, inference (can we "design out" the problems?) ### Rule 4: Worry about Data Quality - Pre-processing, data cleaning, how did this data get here? - Careful! Why is this data missing? --- # Ex: Problems you may not anticipate ### Outcome troubles - Your outcome measure is too variable or measuring what you want in a biased way - Too many outcome measures to detect meaningful effects after multiple testing correction ### Structure in your data - Batch effects - Sample size assuming independence could be incorrect ### Design - Is your goal hypothesis testing, or is it actually estimation? - How to randomize, stratify, identify how to remove bias and confounding? --- # Modeling ### Rule 5: Statistics `\(>\)` Set of Computions - Always EXPLAIN how the methods help you answer the biological question (why did you pick that method?) - Code knowlege `\(\neq\)` statistics knowledge ### Rule 6: Keep it Simple (KISS) - Often provide the strongest results, also interpretability - Careful! curse of overfitting (not generalizable) --- # Rule 8: Check Assumptions ### The Big Ones: - Normality - Independence - Missing Data (bias related to missingness not at random) -- ### Careful! - Some models/tests are more robust to deviations than others - Skewness can give you very weird results - Systematic bias (i.e. in sampling) - Visual checks (i.e. plot residuals from a regression) - You may need: nonparametric analysis, survival analysis, longitudinal analysis --- # Ex: Parametric vs Non-parametric Tests? ### Often misunderstood - T-tests assume normality of the population, but in *large* samples the central limit theorem usually "kicks in" since distribution of means are usually normal (but again, unders assumptions! independence!) + Ratios or "fold changes" are not normally distributed - Wilcoxon test or other common nonparametric tests do not assume normality, but you are no longer testing means (nor medians, unless specific assumptions are met) + outcome: ordinal or interval + can have lower power in small samples, but more conservative - Common nonparametric tests often performed by replacing data with ranks --- # Practice Sound Science ### Rule 9: When Possible, Replicate! - P-hacking, overtesting, overselecting, overfitting --> results cannot stand the test of time (replication) - Replicate using new data - Know your limitations (small sample, biased sampling, unmeasured confounding) and remove those issues next time. Learn from your study! ### Rule 10: Make Your Analysis Reproducible - Minimum standard - Given same data, description of analysis --> reproduce all results/tables/figures - Use reproducible code tools (i.e R Markdown), version control (i.e. git) --- # Example: Multiple testing ### Scary but real - Each test has a nonzero (likely 5%) probability of incorrectly claiming significance - Each test you make increases this error rate - Know what type I error and False Discovery Rate (FDR) and Family-Wise Error Rate (FWER) mean and what the differences are - If you want to relax the error rates, you are doing an *exploratory* study. No denial. Now, replicate! --- # Misc. Errors to Avoid - Acknowledge the ways the data are SELECTED prior to formal analyses - Do not use the same data set to both generate and test hypotheses - Relatedly, practice safe EDA (exploratory data analysis) + Use EDA to visualize distributions and look for outliers or possible model misspecifications, but [don't choose which hypotheses to test after EDA](https://en.wikipedia.org/wiki/Testing_hypotheses_suggested_by_the_data) (unless your study is truly exploratory) - Use dot plots when you have small samples (not bar plots, or even just boxplots) ![](minnier_biodata_files/figure-html/unnamed-chunk-2-1.png) --- # Similar Articles/References - Harrel, Frank. [Manuscript Checklist](http://biostat.mc.vanderbilt.edu/wiki/Main/ManuscriptChecklist) on Vanderbilt Biostatistics website. - Wicherts, Jelte M., et al. ["Degrees of freedom in planning, running, analyzing, and reporting psychological studies: A checklist to avoid p-hacking."](https://www.frontiersin.org/articles/10.3389/fpsyg.2016.01832/full) Frontiers in Psychology 7 (2016): 1832. - Marino, Miguel. ["Reflections from a statistical editor: elements of great manuscripts."](http://www.annfammed.org/content/15/6/504.short) (2017): 504-506. - Zinsmeister, Alan R., and Jason T. Connor. ["Ten common statistical errors and how to avoid them."](https://www.nature.com/articles/ajg20085055) The American journal of gastroenterology 103.2 (2008): 262. - Altman, Douglas G., and J. Martin Bland. ["Improving doctors' understanding of statistics."](http://www.jstor.org/stable/2983040) Journal of the Royal Statistical Society. Series A (Statistics in Society) (1991): 223-267. --- background-image: url(phackingchecklist.png) # Checklist avoid p-hacking, Wicherts et al --- # Resources on Campus Biostatistics and Design Program (BDP) - Email<EMAIL_ADDRESS>- Campus-wide (University Shared Resource) - Drop in hours on Tuesday - Can use Dean’s award or USR awards to pay for core services for grants - https://www.ohsu.edu/xd/research/research-cores/bdp.cfm Knight Cancer Institute Biostatistics Shared Resource (BSR) - For Knight Cancer Institute members/investigators - Pre-award help is subsidized - Submit project request: https://bridge.ohsu.edu/research/knight/resources/BSR/SitePages/Project%20Requests.aspx West Campus: BBU Biostatistics and Bioinformatics Unit - Email Suzi Fei - http://www.ohsu.edu/xd/research/centers-institutes/onprc/research-services/research-support/Biostatistics-a-Bioinformatics.cfm --- # Courses at OHSU School of Public Health Courses - BSTA 523 Design of Experiments + Statistical principles of research design and analysis - PHPM 524 Introduction to Biostatistics - PHPM 525/BSTA 511 Biostatistics I: Estimation and Hypothesis Testing in Applied Biostatistics Human Investigations Program (HIP) - HIP 528 and 529: Applied Biostatistics I and II CSEE Computer Sci/Electrical Engineering - Data Science classes - MATH 530/630 Probability & Statistical Inference for Scientists and Engineers --- # Learn Statistics - [Modern Dive](http://moderndive.com/) An Introduction to Statistical and Data Sciences via R - Chester Ismay & Albert Kim - [Biostatistics for Biomedical Research](http://www.fharrell.com/doc/bbr.pdf) - Frank E Harrell Jr & James C Slaughter, from [ClinStat Class at Vanderbilt](http://biostat.mc.vanderbilt.edu/wiki/Main/ClinStat) - Coursera, edX, Data Camp --- # Thank you!
 Contact:  minnier-[at]-ohsu.edu,  [datapointier](https://twitter.com/datapointier),  [jminnier](https://github.com/jminnier/) Slides available at <http://bit.ly/biodata-stats>
 Code for slides available at <https://github.com/jminnier/talks_etc> Slides created via the R package [xaringan](https://github.com/yihui/xaringan) by [Yihui Xie](https://twitter.com/xieyihui?lang=en) with the metropolis theme


Use Specific Key
ssh -i ~/.ssh/id_rsa [user]@[host]
Use Alternative Port
ssh -i ~/.ssh/id_rsa -p [port] [user]@[host]
Dynamic SOCKS Proxy
This can be used with proxychains to forward client traffic through the remote server.
ssh -D8080 [user]@[host]
Local Port Forwarding
This will bind to [bindaddr]:[port] on the client and forward through the SSH server to the [dsthost]:[dstport]
ssh -L [bindaddr]:[port]:[dsthost]:[dstport] [user]@[host]
Remote Port Forwarding
This will bind to [bindaddr]:[port] on the remote server and tunnel traffic through the ssh client side to [localhost]:[localport]
ssh -R [bindaddr]:[port]:[localhost]:[localport] [user]@[host]
Execute a One Liner
ssh -i ~/.ssh/id_rsa [user]@[host] "sudo apt-get update && sudo apt-get upgrade
Generating Keys
ssh-keygen
Adding Authorized Keys
cat id_rsa.pub >> ~/.ssh/authorized_keys
The following will remotely copy your public key to authorized_keys on [host]
ssh-copy-id -i ~/.ssh/id_rsa [user]@[host]


From to Back to the policy
| Title: | |
| Approving committee: | |
| Date of first approval: | |
| Minute reference: | |
| Document owner: | |
| Date of Equality Impact Assessment: | |
| Equality Impact Assessment Outcome: | |
| Latest review date: | |
| Next review date: | |
NB: The background color shows if text has been added or removed


362_intdude.py
class Solution:
def maxProbability(self, n: int, edges: List[List[int]], succProb: List[float], start: int, end: int) -> float:
neighbors = [[] for i in range(n)]
for i in range(len(edges)):
x, y = edges[i]
neighbors[x].append([y,succProb[i]])
neighbors[y].append([x,succProb[i]])
pq = [[-1.0, start]]
visited = [False]*n
while len(pq) > 0:
tmp = heapq.heappop(pq)
pro = -tmp[0]
pos = tmp[1]
if visited[pos] is True:
continue
visited[pos] = True
if pos == end:
return pro
for x in neighbors[pos]:
nex = x[0]
if visited[nex] is False:
pp = pro*x[1]
heapq.heappush(pq, [-pp, nex])
return 0.0


I know several programming languages.
I have built many apps.
I am studying computer science because it is my favorite topic.
| Name | Gender | Fun Fact About Person |
|---|---|---|
| Jane Doe | Female | Likes to ride bikes |
| John Doe | Male | Likes to ski |
| Bill Stevenson | Male | Likes to code |


Shepherd's Pie
Ingredients
- 1 tbsp sunflower oil
- 1 large onion
- 2-3 medium carrots
- 500g pack lamb mince
- 2 tbsp tomato puree
- large splash of Worcestershire sauce
- 500ml beef stock
- 900g potatoes
- 85g butter
- 3 tbsp milk
Instructions
- Heat the oil in a medium saucepan, then soften the onion and carrots for a few mins. When soft, turn up the heat, crumble in the lamb and brown, tipping off any excess fat. Add the tomato purée and Worcestershire sauce, then fry for a few mins. Pour over the stock, bring to a simmer, then cover and cook for 40 mins, uncovering halfway.
- Meanwhile, heat the oven to 180C/ fan 160C/ gas 4, then make the mash. Boil the potatoes in salted water for 10-15 mins until tender. Drain, then mash with the butter and milk.
- Put the mince into an ovenproof dish, top with the mash and ruffle with a fork. The pie can now be chilled and frozen for up to a month. Bake for 20-25 mins until the top is starting to colour and the mince is bubbling through at the edges. (To bake from frozen, cook at 160C/fan 140C/gas 3 for 1 hr-1 hr 20 mins until piping hot in the centre. Flash under the grill to brown, if you like.) Leave to stand for 5 mins before serving.
Rate this recipe below!


Component: {{detailsright.componentName.data}}
Version: {{detailsright.version.data}}
Organization: {{detailsright.organization.data}}
Last Activity Date: {{getDate(detailsright.lastActivityDate.data)}}
Last View Date: {{getDate(detailsright.lastViewedDate.data)}}
Views: {{detailsright.componentViews.data}}
The main component details are empty
Description:
There is no description for this component
Reusability Factors (5=best)
There is no evaluation score set for this component
Resources:
| Resource Type / Link |
|
{{resource.resourceTypeDesc}}
|
There are no resources listed for this component
Component Vitals:
|
{{attribute.typeDescription}}
|
{{attribute.codeDescription}}
|
|
{{metadata.label}}
|
{{metadata.value}}
|
There are no component vitals listed for this component
Sub Components:
{{detailsright.subComponents.data}}
There are no subcomponents listed for this component
Dependencies:
| Dependency |
Version |
Comment |
Update Date |
| {{dependency.dependency}} |
{{dependency.version}} |
{{dependency.comment}} |
{{getDate(dependency.updateDts)}} |
There are no dependencies listed for this component
Reviews
Title: {{review.title}}——I would recommend this component
Reviewer: {{review.username}}
Role: {{review.userType}}
Time used: {{review.usedTimeCode}}
Last used: {{getDate(review.lastUsed)}}
Organization: {{review.organization}}
Pros: {{pro.text}},
Cons: {{con.text}},
Comments: {{review.comment}}
There are no reviews left for this component
Questions
Q:{{question.question}}
— {{question.username}} ({{question.organization}} - {{question.userType}}) {{getDate(question.updateDts)}}
A:{{response.response}} — {{response.username}} ({{response.organization}} - {{response.userType}}) {{getDate(response.updateDts)}}
There are no questions left for this component
Media
Updated: {{getDate(image.updateDts)}}
There is no media for this component


Sets the search index (*.pdx) for a PDF file or a set of PDF files.
| Attribute | Description | Required |
| file | The PDF to set the search index. | Yes, unless a nested resource collection element is used. |
| path | The full or relative path to the search index (*.pdx). | Yes |
| preservelastmodified | Preserve the last modified time of PDF files. | No; defaults to false. |
| failonerror | If false, log a warning message, but do not stop the build, when the PDF file to process does not exist or an error occurs while setting the search index. | No; defaults to true. |
Resource Collections are used to select groups of PDFs to process.
Set the search index for a single PDF
<pdfsetsearchindex file="myfile.pdf" path="pdf/index/bible.pdx"/>
Set the search index for all PDFs in a directory and its sub-directories
<pdfsetsearchindex path="pdf/index/bible.pdx"> <fileset dir="pdf_dir" includes="**/*.pdf"/> </pdfsetsearchindex>


applyFeatures(dData,
lfcFeatures,
ldArgs,
sMarketRel=None,
sLog=None)
| source code
|
- Parameters:
dData , - , Dictionary , containing , data , to , be , used , requires , specific , naming - open/high/low/close/volume
lfcFeatures - List of feature functions, most likely coming from features.py
ldArgs - List of dictionaries containing arguments, passed as **kwargs
There is a special argument 'MR', if it exists, the data will be
made market relative
sMarketRel - If not none, the data will all be made relative to the symbol
provided
sLog - If not None, will be filename to log all of the features to
- Returns:
- list of dataframes containing values
|


/********************************************************************
* Copyright (c) 2018, Douglas Campbell
* Licensed under the MIT License
********************************************************************/
/**
__Image Sonifier__
Generation of audio that represents an image.
Plays and holds notes on a synthesizer, then adjusts the volume of those
notes depending on the brightness of red, green, and blue channels in each
pixel in an image. By regularly re-sampling the image as it is changed,
the sound heard will adjust as the relative colour brightnesses change
within the currently visible image.
Source: [GitHub repository](https://github.com/staplegun/sonifier)
Requires [Tone.js](https://tonejs.github.io/) -
`<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/13.1.4/Tone.js"></script>`
_Implementation notes_
The default tones combine into a 'C 6/9' chord (which uses notes from the
Pentatonic scale giving a drone-like sound):
- Red: Major third
- Green: Fifth
- Blue: Minor third
*/
class Sonifier {
/**
* Constructs a Sonifier.
* @param {Object}
*/
constructor(config) {
// set defaults
this._synthConfig = Sonifier.defaultSynthConfig
this._synthRedNotes = Sonifier.defaultRedNotes
this._synthGreenNotes = Sonifier.defaultGreenNotes
this._synthBlueNotes = Sonifier.defaultBlueNotes
this._dynamicRange = Sonifier.defaultDynamicRange
this._imagePixelSampling = Sonifier.defaultImagePixelSamplingDistance
this._imageAnalysisStrategy = Sonifier.defaultImageAnalysisStrategy
// NB: panning each to give wider soundscape
this._volRed = new Tone.PanVol(0, -10)
this._volGreen = new Tone.PanVol(-0.5, -10)
this._volBlue = new Tone.PanVol(0.5, -10)
this._masterVolume = new Tone.Volume(0)
//let effect = new Tone.Vibrato(1, 0.5)
//let effect = new Tone.Chorus(1, 2.5, 0.2)
//let effect = new Tone.LowpassCombFilter()
let effect = new Tone.Compressor()
// apply supplied config parameters
if (config) {
if (config.synthConfig) this._synthConfig = config.synthConfig
if (config.synthRedNotes) this._synthRedNotes = config.synthRedNotes
if (config.synthGreenNotes) this._synthGreenNotes = config.synthGreenNotes
if (config.synthBlueNotes) this._synthBlueNotes = config.synthBlueNotes
if (config.dynamicRange && config.dynamicRange >= 1) this._dynamicRange = config.dynamicRange
if (config.imagePixelSampling && config.imagePixelSampling >= 1) this._imagePixelSampling = config.imagePixelSampling
if (config.imageAnalysisStrategy) this._imageAnalysisStrategy = config.imageAnalysisStrategy
}
// create synths
this._synthRed = new Tone.PolySynth(3, Tone.Synth, this._synthConfig)
this._synthGreen = new Tone.PolySynth(3, Tone.Synth, this._synthConfig)
this._synthBlue = new Tone.PolySynth(3, Tone.Synth, this._synthConfig)
this._synthRed.chain(this._volRed, effect, this._masterVolume, Tone.Master)
this._synthGreen.chain(this._volGreen, effect, this._masterVolume, Tone.Master)
this._synthBlue.chain(this._volBlue, effect, this._masterVolume, Tone.Master)
}
/**
* Starts playing the synthesizer notes for the red channel.
*/
playRed() {
this._synthRed.triggerAttack(this._synthRedNotes)
}
/**
* Starts playing the synthesizer notes for the green channel.
*/
playGreen() {
this._synthGreen.triggerAttack(this._synthGreenNotes)
}
/**
* Starts playing the synthesizer notes for the blue channel.
*/
playBlue() {
this._synthBlue.triggerAttack(this._synthBlueNotes)
}
/**
* Starts playing the synthesizer notes for all (red/green/blue) channels.
*/
play() {
console.log("Playing sonifier")
this.playRed()
this.playGreen()
this.playBlue()
}
/**
* Stops playing the synthesizer notes for the red channel.
*/
releaseRed() {
this._synthRed.triggerRelease(this._synthRedNotes)
}
/**
* Stops playing the synthesizer notes for the green channel.
*/
releaseGreen() {
this._synthGreen.triggerRelease(this._synthGreenNotes)
}
/**
* Stops playing the synthesizer notes for the blue channel.
*/
releaseBlue() {
this._synthBlue.triggerRelease(this._synthBlueNotes)
}
/**
* Stops playing the synthesizer notes for all (red/green/blue) channels.
*/
release() {
console.log("Silencing sonifier")
this.releaseRed()
this.releaseGreen()
this.releaseBlue()
}
/**
* Changes the red channel synthesizer to the specified volume.
* @param {Number} - New volume: 0 (silence) - 255 (max)
*/
volumeRed(vol = 100) {
this._volRed.volume.rampTo(Sonifier.toDecibelSine(vol, this._dynamicRange), 0.5)
}
/**
* Changes the green channel synthesizer to the specified volume.
* @param {Number} - New volume: 0 (silence) - 255 (max)
*/
volumeGreen(vol = 100) {
this._volGreen.volume.rampTo(Sonifier.toDecibelSine(vol, this._dynamicRange), 0.5)
}
/**
* Changes the blue channel synthesizer to the specified volume.
* @param {Number} - New volume: 0 (silence) - 255 (max)
*/
volumeBlue(vol = 100) {
this._volBlue.volume.rampTo(Sonifier.toDecibelSine(vol, this._dynamicRange), 0.5)
}
/**
* Changes the master volume to the specified volume.
* @param {Number} - New volume: -60 (silence) - 0 (max)
*/
volumeMaster(vol = -10) {
this._masterVolume.volume.rampTo(vol, 0.5)
}
/**
* Calculates an appropriate decibel volume for the supplied value.
* Converts from pixel brightness (0 to 255) to decibel (-dynamicRange to 0).
*
* Applies a sinusoidal curve so low & high values are compressed
* (less pronounced change) and mid-range values are expanded
* (more pronounced change). Rationale: brightness changes nearer very
* bright or very dark are less noticeable, so we want to reflect
* that in the resulting volume.
*
* The default dynamic range is -30 to 0 dB. NB: -60 dB is absolute silence
* in Tone.js, we use -30 dB as the minimum so there is always some sound.
*
* @param {Number} - Range: 0 (silence) - 255 (max)
* @param {Integer} - Range of values to return to represent from silence to maximum volume: 0 - 60
* @return {Number} - Range: -30 (silence) - 0 (max)
*/
static toDecibelSine(value, dynamicRange = Sonifier.defaultDynamicRange) {
// convert vol (range 0-255) into sinusoidal -1 - +1, then adjust to desired dynamic range
// we only want a half cycle of the sine wave (from min to max)
// see: http://mathonweb.com/help_ebook/html/trigonometry.htm#sinusoidal
// a. phase length: divide value by 255 so in range 0-1,
// multiply by pi so half cycle is in range 0-1
// b. phase shift: subtract half pi (so we start at min value)
// c. calculate sine, giving range -1 to +1
// d. amplitude: multply by half dynamic range (giving range e.g. -15 to +15),
// subtract half dynamic range so final range is e.g. -30 to 0
return ((dynamicRange / 2) * Math.sin( (3.141 * value / 255) - (3.141 / 2) )) - (dynamicRange / 2)
}
/**
* Analyses once the image data in the HTML canvas in the specified HTML
* element and adjusts the appropriate sonifier volumes.
* NB: The sonifier must already be playing for any sound to be heard.
*
* Supported image analysis strategies:
* - `absolute` = translate each channel brightness value to an equivalent volume value (default)
* - `tiers` = set the min/mid/max channel brightnesses to pre-defined volume tiers
*
* @param {Object} - HTML Canvas Element
* @param {String}
*/
analyseCanvas(canvasElement, imageAnalysisStrategy = this._imageAnalysisStrategy) {
if (canvasElement === undefined || canvasElement == null) {
return
}
switch (imageAnalysisStrategy) {
case 'tiers':
this.analyseImageTiers(
canvasElement.getContext("2d")
.getImageData(0, 0, canvasElement.width, canvasElement.height)
)
break;
default:
this.analyseImageAbsolutes(
canvasElement.getContext("2d")
.getImageData(0, 0, canvasElement.width, canvasElement.height)
)
}
}
// TODO possible new strategy: divide image into 9 zones and analyse independently
// e.g. if 2/3 grass and 1/3 sky, the overall averages just see a lot of blue
/**
* Analyses once the supplied image data and adjusts the appropriate
* sonifier volumes.
* NB: The sonifier must already be playing for any sound to be heard.
*
* Sets each channel volume based on its absolute average brightness.
*
* This strategy is accurate, but many images contain such a range of
* colours that the channel averages end up in a similar range (50-180).
* We use a sinusoidal compression to expand this mid-range, but often
* the volume changes still don't seem very pronounced.
*
* @param {ImageData} - See: https://developer.mozilla.org/en-US/docs/Web/API/ImageData
*/
analyseImageAbsolutes(imagePixelData) {
if (imagePixelData.height <= 1 || imagePixelData.width <= 1) {
return
}
let brightness = Sonifier.calculateBrightnessAverages(imagePixelData, this._imagePixelSampling)
console.log('Sonifying brightness: R=' + brightness['red'].toFixed(0) + ' G=' + brightness['green'].toFixed(0) + ' B=' + brightness['blue'].toFixed(0))
console.log('Sonifying decibels: R=' + Sonifier.toDecibelSine(brightness['red']).toFixed(0) + ' G=' + Sonifier.toDecibelSine(brightness['green']).toFixed(0) + ' B=' + Sonifier.toDecibelSine(brightness['blue']).toFixed(0))
this.volumeRed(brightness['red'])
this.volumeGreen(brightness['green'])
this.volumeBlue(brightness['blue'])
}
/**
* Analyses once the supplied image data and adjusts the appropriate sonifier volumes.
* NB: The sonifier must already be playing for any sound to be heard.
*
* Has three set volume tiers (defined in Sonifier.tierVolumes) and uses
* only those volume levels for the RGB channel volumes based on which is
* brightest, middle, and dimmest. In addition, an overall volume is set
* based on the absolute brightness of the brightest channel - this provides
* some variation for black & white images (which have the same brightness
* for all three RGB channels).
*
* This strategy gives more obvious volume changes, but is fairly
* artificial (e.g. all three may be similar brightness but the one
* slightly brighter gets a very high volume).
*
* @param {ImageData} - See: https://developer.mozilla.org/en-US/docs/Web/API/ImageData
*/
analyseImageTiers(imagePixelData) {
if (imagePixelData.height <= 1 || imagePixelData.width <= 1) {
return
}
let brightness = Sonifier.calculateBrightnessAverages(imagePixelData, this._imagePixelSampling)
let min = Math.min(brightness['red'], brightness['green'], brightness['blue'])
let max = Math.max(brightness['red'], brightness['green'], brightness['blue'])
// multiplier for overall brightness (0-1)
let multiplier = max / 255
// set the volume for each channel using the predefined volume tiers
let red, green, blue
switch (brightness['red']) {
case min:
red = Sonifier.tierVolumes[0] * multiplier
break;
case max:
red = Sonifier.tierVolumes[2] * multiplier
break;
default:
red = Sonifier.tierVolumes[1] * multiplier
}
switch (brightness['green']) {
case min:
green = Sonifier.tierVolumes[0] * multiplier
break;
case max:
green = Sonifier.tierVolumes[2] * multiplier
break;
default:
green = Sonifier.tierVolumes[1] * multiplier
}
switch (brightness['blue']) {
case min:
blue = Sonifier.tierVolumes[0] * multiplier
break;
case max:
blue = Sonifier.tierVolumes[2] * multiplier
break;
default:
blue = Sonifier.tierVolumes[1] * multiplier
}
console.log('Sonifying brightness: R=' + brightness['red'].toFixed(0) + ' G=' + brightness['green'].toFixed(0) + ' B=' + brightness['blue'].toFixed(0))
console.log('Sonifying tiered: R=' + red.toFixed(0) + ' G=' + green.toFixed(0) + ' B=' + blue.toFixed(0))
console.log('Sonifying decibels: R=' + Sonifier.toDecibelSine(red).toFixed(0) + ' G=' + Sonifier.toDecibelSine(green).toFixed(0) + ' B=' + Sonifier.toDecibelSine(blue).toFixed(0))
this.volumeRed(red)
this.volumeGreen(green)
this.volumeBlue(blue)
}
/**
* Calculates the average brightness of pixels in the supplied image data.
* Only samples every Nth pixel (in a grid across the whole image)
* to improve performance.
*
* @param {ImageData} - See: https://developer.mozilla.org/en-US/docs/Web/API/ImageData
* @param {Integer} - How many pixels to sample, i.e. every Nth pixel
* @return {Object} - properties for each channel (range 0-255): 'red', 'green', 'blue'
*/
static calculateBrightnessAverages(imagePixelData, imagePixelSamplingDistance = Sonifier.defaultImagePixelSamplingDistance) {
let width = imagePixelData.width
let height = imagePixelData.height
let red = 0, green = 0, blue = 0
// let alpha, grey
// NB: use less variable memory by adding up all values for each channel, then extrapolate
for (let col = 0; col < width; col += imagePixelSamplingDistance) {
for (let row = 0; row < height; row += imagePixelSamplingDistance) {
red += imagePixelData.data[Sonifier.getColorIndicesForCoord(col, row, width)[0]]
green += imagePixelData.data[Sonifier.getColorIndicesForCoord(col, row, width)[1]]
blue += imagePixelData.data[Sonifier.getColorIndicesForCoord(col, row, width)[2]]
// alpha += imagePixelData.data[ Sonifier.getColorIndicesForCoord(col, row, width)[3] ]
// grey += (red + green + blue) / 3
// console.log(col + 'x' + row + ': ' + red + ',' + green + ',' + blue + ',' + alpha )
}
}
// extrapolate total sampled channel values across the whole image to get average
// - assume every pixel in the sampled square has the same value
// - then divide by total pixels in the image
red = red * (imagePixelSamplingDistance * imagePixelSamplingDistance) / (width * height)
green = green * (imagePixelSamplingDistance * imagePixelSamplingDistance) / (width * height)
blue = blue * (imagePixelSamplingDistance * imagePixelSamplingDistance) / (width * height)
return {
"red": red,
"green": green,
"blue": blue
}
}
/**
* Starts regular analysis of the specified HTML canvas element at the
* specified time interval.
* NB: The sonifier must already be playing for any sound to be heard.
*
* @param {Object}
* @param {Number} - How often to analyse the canvas in seconds
*/
pollCanvasStart(canvasElement, intervalSecs = 2) {
this._pollTimer = setInterval(function() {
sonifier.analyseCanvas(canvasElement)
}, intervalSecs * 1000)
}
/**
* Stops the regular analysis of the specified HTML canvas element.
* NB: The sonifier will continue to play the existing notes until stopped.
*/
pollCanvasStop() {
clearInterval(this._pollTimer)
}
/**
* Calculates the offset inside an ImageData array that the specified pixel
* data is. Returns an array of four offsets for the four bytes describing
* the single pixel (RGBA), e.g. `getColorIndicesForCoord(x,y,w)[2]`
* returns the pixel's blue value
*
* See: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas
*
* @param {Integer}
* @param {Integer}
* @param {Integer}
* @return {Array} - Absolute array offsets for the four bytes describing the single pixel (RGBA)
*/
static getColorIndicesForCoord(x, y, imageWidth) {
let redOffset = y * (imageWidth * 4) + x * 4
return [redOffset, redOffset + 1, redOffset + 2, redOffset + 3]
}
}
Sonifier.defaultSynthConfig = {
"oscillator": {
"type": "fatsine",
"count": 3,
"spread": 30
},
"envelope": {
"attack": 0.01,
"decay": 0.1,
"sustain": 0.5,
"release": 5.0,
"attackCurve": "exponential"
}
}
Sonifier.defaultRedNotes = ['C2', 'E2']
Sonifier.defaultGreenNotes = ['G3', 'D4']
Sonifier.defaultBlueNotes = ['A3', 'C4']
Sonifier.defaultDynamicRange = 30
Sonifier.defaultImagePixelSamplingDistance = 10
Sonifier.defaultImageAnalysisStrategy = 'absolute'
Sonifier.tierVolumes = [80, 180, 255]


Pet dog Freddie saves woman who has 100 seizures a day - without training
Lucy, 20, has had to give up her job, has lost friends and has moved back in with her parents
by Neil ShawA woman who suffers up to 100 seizures a day is regularly rescued by her dog - which can recognise her distress despite never being trained.
Lucy Brown gave up her job and lost her freedom after being struck down by non-epileptic attack disorder (NEAD).
The condition has forced the former carer to leave the house she shared with her boyfriend of five years and move back in with her parents for her own safety.
Lucy, 20, said she has also had to sign on for benefits and has lost several friendships since being hit by NEAD as she can't drink or go out.
But one thing has kept her going through the difficult times - her pet dog Freddie.
Despite no training Freddie acts like a seizure dog - whenever she fits he licks and paws at her and brings her round.
The two-year-old Labrador acts as Lucy's safety net, keeping her out of harm when there is nobody else around.
She said: "He does what seizure dogs do - he licks me and paws me to bring me round but has never had any training.
"He's the main reason I moved back home. He will help me when I'm on my own. He's my dog - I got him as a puppy. He's always by my side and will just lie with me.
"I can't remember the first time he helped but, from what I’ve been told, he just ran straight over to me, starting licking my face and cuddled his body into me."
Lucy, from Warrington, Cheshire said she first suffered seizures when she was in her mid-teens but they quickly disappeared.
However, the condition returned with a vengeance at the start of 2019 - turning her life upside down.
Although doctors initially thought she had epilepsy medication prescribed to her put her in hospital - leading staff to run a series of tests that eventually led to NEAD.
Symptoms include convulsions and loss of bladder control - all epilepsy-like indicators.
She said: "It's just been getting me depressed - losing my job and everything. Everyone is moving on with their lives and I'm held back.
"It's very lonely. I don't really do much. I can't even have a bath alone.
"I average about ten seizures a day, although it was up around 100 in February. They range from staring into space to full-on fits.
"I have to make sure I'm in a safe place. A couple of times a month they go above 20 or 30 a day.
"The seizures don't really have a trigger.
"When I first started having them I was still going out and I would always get them when I got home, so I thought it could be the lights.
"Car headlights always look like they are on full beam, too. But I still don't think that's right."
Lucy said her partner Bradley, 20, has been great.
But the condition has meant she can't go out and drink anymore - meaning she has drifted away from some people.
She said: "It's just embarrassing going out. Socialising is just no good as you're in fear of having one [a seizure]. I've lost a lot of friends.
"Friends use to invite me to go out but due to so many last-minute cancellations they naturally stopped asking.
"I get occasional texts off of a couple of people but I just have lost contact with a lot as I rely on others. I won’t go anywhere on my own."
Lucy said the attacks can strike at any time - and there's no telling when they might stop.
 But it could also stop tomorrow. I've got some other health problems - I'm going through some tests at the moment.
"They want to rule out epilepsy completely although I'm already sure it's not. They have to be 100 per cent sure as if you're not on medication it can damage your brain."
Lucy now wants to speak out to raise awareness.
It is estimated that around 15,000 people in the UK have the condition, according to a NEAD support website - although that figure could be much higher.
She said: "A lot of people get diagnosed with epilepsy and actually have NEAD. It's about awareness.
"Epilepsy drugs are really toxic for your body so it's not good to be on the medication [if you don't need them]."
Lucy has tried counselling for the condition but, aside from that, said there is not much that can be done - including surgery and other treatments.
She said: "Counselling was the only option for me."


Hopefully you saw our big announcement yesterday about support for Shadow DOM v1 Slots in Aurelia. It's an exciting milestone for us on our road towards Release Candidate and as part of our commitment to web standards. Today, we have a number of patch releases to various Aurelia libraries. The list is relatively small. You can read the details below.
Release Notes
Note: The Shadow DOM v1 features are not included in the mainline releases. Those are an out-of-band release at the moment so that the community can choose whether to update now or wait.
aurelia-polyfills 1.0.0-beta.1.1.5
Features
- console: moved console fix from logging-console to polyfills ( 6db2334a )
aurelia-logging-console 1.0.0-beta.1.2.2
Bug Fixes
- index: moved console polyfill to aurelia-polyfills ( 073d49dc )
aurelia-http-client 1.0.0-beta.1.2.2
Bug Fixes
- Fix request-message to account for existing query strings in urls.


Select Floor
Floor 1
Floor 2
Floor 3
Select Team
Admin
event_seat
view_compact
view_compact
stop
stop_circle
save
cloud
edit
done_all
view_sidebar
pie_chart
receipt_long
event_seat
close
360
add
remove
delete
cancel
close
Total Seats :
Reserved Seats (
event_seat
) :
Hot Seats (
event_seat
) :
Alloted Seats (
event_seat
) :
Vaccant Seats (
event_seat
) :
Disabled Seats (
event_seat
) :


AtomPub Manager
New
Open
Save
Delete
|
Preview
Edit
|
Media
Open
x
Media
x
Upload to:
File:
Title:
Author:
Summary:
Author
Name:
URI:
Summary
Time
Updated
Published


Refers to an image or graphic that is external to the filter element that is loaded and rendered as part of the filter primitive. The image can link to an external image, or reference another snippet of SVG. It produces an image similar to the built in SourceGraphic, except it comes from an external source.
Syntax
<feImage xlink:href = "images/artgraphic.png"/>
DOM Information
Inheritance Hierarchy
Members
The SVGFEImageElement object has these types of members:
Properties
The SVGFEImageElement object has these properties.
| Property | Description |
|---|---|
|
Gets a value that indicates whether referenced resources that are not in the current document are required to correctly render a given element. | |
|
Gets or sets the height of an element. | |
|
Provides a reference for the output result of a filter. | |
|
Defines the width of an element. | |
|
Gets or sets the x-coordinate value. | |
|
Gets or sets a value that specifies the language that is used in the contents and attribute values of an element. | |
|
Gets or sets a value that indicates whether white space is preserved in character data. | |
|
Gets or sets the y-coordinate value. |
Standards information
- Scalable Vector Graphics: Filter Effects, Section 15.25.20
Build date: 1/13/2014


Settings
Configure the app and change your information
Settings
Edit my timetable
Clear all my information (Delete account)
Back to the main menu


T
- the type of the asynchronous computation resultpublic interface Future<T> extends InterruptHandler
Future
is an abstraction to deal with asynchronicity without having to use callbacks directly or blocking threads. The primary usage for Futures
on the JVM is to perform IO operations, which are asynchronous by nature.
Although most IO APIs return synchronously, they do that by blocking the current Thread
. For instance, the thread issues a request to a remote system and then waits until a response comes back. Considering that the JVM uses native threads, it is wasteful to block them since it leads to potential thread starvation and higher garbage collection pressure. It is hard to scale a JVM system vertically if the IO throughput is bounded by the number of threads.
From the user perspective, a Future
can be in three states:
Instead of exposing this state to the user, Future
provides combinators to express computations that run once the Future
completes. The results of these combinators are Future
instances that can be used to perform other transformations, giving the user a powerful tool to express complex chains of asynchronous transformations.
Let’s say that we need to call a remote service to get the username given an id:
Future<User> user = userService.get(userId);
It’s possible to apply the map
transformation that produces a Future
for the username string:
Future<String> username = user.map(user -> user.username);
Note that we are using a lambda expression (user -> user.username
) that takes a user and returns its username.
Let’s say that now we need to call a service to validate the username string. This is the result if we use the map
combinator for it:
Future<Future<Boolean>> isValid =
username.map(username -> usernameService.isValid(username));
Given that the lambda expression calls another service and returns a Future
, the produced result is a nested future (Future<Future<Boolean>>
). One alternative to flatten this nested result is using Future.flatten
:
Future<Boolean> isValidFlat = Future.flatten(isValid);
There’s a convenient combinator called flatMap
that applies both map
and Future.flatten
at once:
Future<Boolean> isValid =
username.flatMap(username -> usernameService.isValid(username));
The flatMap
combinator is very flexible and comes from the monad abstraction. Although useful, learning monads and category theory is not a requirement to use Future
s. Strictly speaking, Future
isn’t a monad since it uses eager evaluation and thus breaks referential transparency. Once a Future
is created, it is already running. See the “Execution Model” section for more information.
There are many other useful operators to deal with exceptions, collections of futures, and others.
| Modifier and Type | Field and Description |
|---|---|
static Future<Void> |
VOID
A constant void future.
|
| Modifier and Type | Method and Description |
|---|---|
static <T> Future<T> |
apply(java.util.function.Supplier<T> s)
Creates a future with the result of the supplier.
|
<U,R> Future<R> |
biFlatMap(Future<U> other,
java.util.function.BiFunction<? super T,? super U,? extends Future<R>> f)
Waits for this and other (running in parallel), maps the result with f, and flattens the result.
|
<U,R> Future<R> |
biMap(Future<U> other,
java.util.function.BiFunction<? super T,? super U,? extends R> f)
Waits for this and other (running in parallel) and then maps the result with f.
|
static <T> Future<List<T>> |
collect(List<? extends Future<T>> list)
Transforms a list of futures into a future of a list.
|
Future<T> |
delayed(long delay,
TimeUnit timeUnit,
ScheduledExecutorService scheduler)
Delays the result of this future.
|
static <T> Future<List<T>> |
emptyList()
Returns a satisfied future with an immutable empty list.
|
static <T> Future<Optional<T>> |
emptyOptional()
Returns a satisfied future with an empty optional.
|
Future<T> |
ensure(Runnable r)
Runs r when this future completes.
|
static <T> Future<T> |
exception(Throwable ex)
Creates a failed future.
|
static <T> Future<T> |
firstCompletedOf(List<Future<T>> list)
Finds the first future that completes.
|
<R> Future<R> |
flatMap(java.util.function.Function<? super T,? extends Future<R>> f)
Maps the result of this future to another future and flattens the result.
|
static <T> Future<T> |
flatten(Future<Future<T>> fut)
Flattens a nested future.
|
T |
get(long timeout,
TimeUnit unit)
Blocks the current thread until this future is satisfied and gets its result.
|
Future<T> |
interruptible()
Creates a future that will be completed with the interrupt exception if an interrupt is received.
|
boolean |
isDefined()
Checks if this future is completed.
|
static <T> Future<Void> |
join(List<? extends Future<T>> list)
This method is similar to collect, but it discards the result of the futures.
|
void |
join(long timeout,
TimeUnit unit)
Blocks the current thread until this future is satisfied.
|
<R> Future<R> |
map(java.util.function.Function<? super T,? extends R> f)
Maps the result of this future to another value.
|
static <T> Future<T> |
never()
Returns a future that is never satisfied.
|
Future<T> |
onFailure(java.util.function.Consumer<Throwable> c)
Executes the Consumer if this future completes with an exception.
|
Future<T> |
onSuccess(java.util.function.Consumer<? super T> c)
Executes the Consumer if this future completes successfully.
|
void |
proxyTo(Promise<T> p)
Proxies the result of this future, successful or not, to a Promise.
|
Future<T> |
rescue(java.util.function.Function<Throwable,? extends Future<T>> f)
If this future completes with an exception, applies the provided rescue function and flattens the result.
|
Future<T> |
respond(Responder<? super T> r)
Executes the Responder once this future completes.
|
static <T> Future<Integer> |
selectIndex(List<Future<T>> list)
Selects the index of the first satisfied future.
|
<R> Future<R> |
transform(Transformer<? super T,? extends R> t)
Maps the result of this future using the provided Transformer.
|
<R> Future<R> |
transformWith(Transformer<? super T,? extends Future<R>> t)
Maps the result of this future using a Transformer that returns another future and flattens the result.
|
default <R> Future<R> |
unsafeCast()
Casts the result of this future.
|
static <T> Future<T> |
value(T v)
Creates a successful future.
|
Future<Void> |
voided()
Creates a future that is satisfied with void when this future completes.
|
static <T> Future<Void> |
whileDo(java.util.function.Supplier<Boolean> cond,
java.util.function.Supplier<Future<T>> f)
Executes the supplier function while the condition is valid.
|
default Future<T> |
within(long timeout,
TimeUnit timeUnit,
ScheduledExecutorService scheduler)
Creates a future that fails with a TimeoutException if this future isn’t completed within the timeout.
|
Future<T> |
within(long timeout,
TimeUnit timeUnit,
ScheduledExecutorService scheduler,
Throwable exception)
Creates a future that fails with a exception if this future isn’t completed within the timeout.
|
apply, apply, raise
static <T> Future<T> never()
Returns a future that is never satisfied.
T
- the type of the never satisfied future.static <T> Future<T> apply(java.util.function.Supplier<T> s)
Creates a future with the result of the supplier. Note that the supplier is executed by the current thread. Use FuturePool.async to execute the supplier on a separate thread.
T
- the type of the value returned by the Supplier.s
- a supplier that may throw an exceptionstatic <T> Future<T> value(T v)
Creates a successful future.
T
- the type of the value.v
- the value that satisfies the future.static <T> Future<T> exception(Throwable ex)
Creates a failed future.
T
- the type of the failed future.ex
- the failure.static <T> Future<T> flatten(Future<Future<T>> fut)
Flattens a nested future. The usage of this method indicates a code smell: a map may have been used instead of flatMap. There are genuine scenarios where flatten is required, though.
T
- the type of the future resultfut
- the nested futurestatic <T> Future<List<T>> emptyList()
Returns a satisfied future with an immutable empty list.
T
- the list typestatic <T> Future<Optional<T>> emptyOptional()
Returns a satisfied future with an empty optional.
T
- the optional typestatic <T> Future<List<T>> collect(List<? extends Future<T>> list)
Transforms a list of futures into a future of a list.
list
- the futures to collect fromstatic <T> Future<Void> join(List<? extends Future<T>> list)
This method is similar to collect, but it discards the result of the futures. It’s useful to wait for a list of pending future side effects.
list
- the futures to wait forstatic <T> Future<Integer> selectIndex(List<Future<T>> list)
Selects the index of the first satisfied future.
list
- the list of futures to select fromstatic <T> Future<T> firstCompletedOf(List<Future<T>> list)
Finds the first future that completes.
list
- futures to select from.static <T> Future<Void> whileDo(java.util.function.Supplier<Boolean> cond, java.util.function.Supplier<Future<T>> f)
Executes the supplier function while the condition is valid.
cond
- a supplier that determines if the while should stop or notf
- the body of the while that is executed on each asynchronous iteration<R> Future<R> map(java.util.function.Function<? super T,? extends R> f)
Maps the result of this future to another value.
f
- the mapping function.<R> Future<R> flatMap(java.util.function.Function<? super T,? extends Future<R>> f)
Maps the result of this future to another future and flattens the result.
f
- the mapping function that returns another future instance.<R> Future<R> transform(Transformer<? super T,? extends R> t)
Maps the result of this future using the provided Transformer. If this future completes successfully, transformer.onValue is called. If this future completes with an exception, transformer.onException is called.
t
- a Transformer that applies the transformation.<R> Future<R> transformWith(Transformer<? super T,? extends Future<R>> t)
Maps the result of this future using a Transformer that returns another future and flattens the result. If this future completes successfully, transformer.onValue is called. If this future completes with an exception, transformer.onException is called.
t
- a Transformer that applies the transformation.<U,R> Future<R> biMap(Future<U> other, java.util.function.BiFunction<? super T,? super U,? extends R> f)
Waits for this and other (running in parallel) and then maps the result with f.
other
- The other future that becomes the second parameter of f.f
- the mapping function. The first parameter is the result of this and the second the result of other.<U,R> Future<R> biFlatMap(Future<U> other, java.util.function.BiFunction<? super T,? super U,? extends Future<R>> f)
Waits for this and other (running in parallel), maps the result with f, and flattens the result.
other
- The other future that becomes the second parameter of f.f
- the mapping function. The first parameter is the result of this and the second the result of other.Future<T> ensure(Runnable r)
Runs r when this future completes.
r
- the Runnable to be executed.Future<T> onSuccess(java.util.function.Consumer<? super T> c)
Executes the Consumer if this future completes successfully.
c
- the Consumer to be executed.Future<T> onFailure(java.util.function.Consumer<Throwable> c)
Executes the Consumer if this future completes with an exception.
c
- the Consumer to be executed.Future<T> respond(Responder<? super T> r)
Executes the Responder once this future completes. If this future completes successfully, responder.onValue is called. If this future completes with an exception, responder.onException is called.
r
- the Responder to be executed.Future<T> rescue(java.util.function.Function<Throwable,? extends Future<T>> f)
If this future completes with an exception, applies the provided rescue function and flattens the result.
Note that it’s possible to return a Future.exception from f if the exception can’t be recovered.
f
- the function to be executed.Future<T> interruptible()
Creates a future that will be completed with the interrupt exception if an interrupt is received.
boolean isDefined()
Checks if this future is completed.
T get(long timeout, TimeUnit unit) throws CheckedFutureException
Blocks the current thread until this future is satisfied and gets its result. This method normally only useful for tests, avoid it for production code.
timeout
- for how long the thread should wait for the resultunit
- time unit of the timeoutCheckedFutureException
- wrapper exception used when the result is a checked exception. If the exception is unchecked, it’s thrown without this wrapper.void join(long timeout, TimeUnit unit) throws CheckedFutureException
Blocks the current thread until this future is satisfied. This method normally only useful for tests, avoid it for production code.
This method is similar to get but it doesn’t return the future value nor throws if the future completes with an exception.
timeout
- for how long the thread should wait for the resultunit
- time unit of the timeoutCheckedFutureException
- wrapper exception used when the result is a checked exception. If the exception is unchecked, it’s thrown without this wrapper.Future<Void> voided()
Creates a future that is satisfied with void when this future completes.
Future<T> delayed(long delay, TimeUnit timeUnit, ScheduledExecutorService scheduler)
Delays the result of this future. It method doesn’t take in consideration how long this future takes to be completed. It assumes the state of this future after delay, being it completed or not.
delay
- for how long the future must be delayedtimeUnit
- the time unit for delayscheduler
- used to schedule an internal task to be executed after delay.void proxyTo(Promise<T> p)
Proxies the result of this future, successful or not, to a Promise.
p
- the Promise to be updated once this future completes.default Future<T> within(long timeout, TimeUnit timeUnit, ScheduledExecutorService scheduler)
Creates a future that fails with a TimeoutException if this future isn’t completed within the timeout.
timeout
- how long to wait for the resulttimeUnit
- the time unit of timeout.scheduler
- used to schedule an internal task after the timeout.Future<T> within(long timeout, TimeUnit timeUnit, ScheduledExecutorService scheduler, Throwable exception)
Creates a future that fails with a exception if this future isn’t completed within the timeout.
timeout
- how long to wait for the resulttimeUnit
- the time unit of timeout.scheduler
- used to schedule an internal task after the timeout.exception
- the exception to be thrown when the future times out.default <R> Future<R> unsafeCast()
Casts the result of this future. Avoid this method since it’s unsafe and can produce a future failed with a ClassCastException.
Copyright © 2017. All Rights Reserved.


Great, the orb we need is behind that glass. To open it, bring the left orb to the blue pedestal. But to keep it cool on the way, we will need shadows.
- Open the file
web/common/Game.js
. Note that the shadow/depth map is already almost fully implemented in lines 304 onwards. The render loop can be looked up in the same file
- Finish the initialization as described in the comment marked with TASK4.1. You will need the following function:
- Open the file
web/shaders/tasks/depth.vs
and complete the missing transformation to light space.
- Then open the file
web/shaders/tasks/depth.fs
and set the depth to a value that makes the whole shadow map appear in shadow such that the orbs get cooled down.
- Open the file
web/shaders/tasks/fragmentLighting.vs
and implement the missing transformation.
- Now open the file
web/shaders/tasks/fragmentLighting.fs
and follow the remaining tasks marked with TASK4.1
- Come back here and bring the first orb to the blue pedestal!


Project: VEDAS
Project: KAYA
For Enterprise
Contact
Arupa
AG.
We work alongside our farmers to increase their profitability
& accelerate the transition to sustainable farming.


public class ActivateWrapper
extends java.lang.Object
implements java.rmi.Remote, java.io.Serializable
This wrapper class is assumed to be available directly in the activation group VM; that is, it is assumed to be in the application classloader, the extension classloader, or the boot classloader, rather than being downloaded. Since this class also needs considerable permissions, the easiest thing to do is to make it an installed extension.
This wrapper class performs a security check to control what policy files can
be used with a given codebase. It does this by querying the VM's (global)
policy for SharedActivationPolicyPermission
grants. The service's associated
ActivateDesc.importLocation
is used as the CodeSource
for selecting the appropriate permission setValue to check against. If multiple
codebases are used, then all the codebases must have the necessary
SharedActivationPolicyPermission
grants.
| Modifier and Type | Class and Description |
|---|---|
static class |
ActivateWrapper.ActivateDesc
Descriptor for registering a "wrapped" activatable object.
|
| Constructor and Description |
|---|
ActivateWrapper(java.rmi.activation.ActivationID id,
java.rmi.MarshalledObject data)
Activatable constructor.
|
| Modifier and Type | Method and Description |
|---|---|
static java.rmi.activation.ActivationID |
register(java.rmi.activation.ActivationGroupID gid,
ActivateWrapper.ActivateDesc desc,
boolean restart,
java.rmi.activation.ActivationSystem sys)
Analog to
Activatable.register() for activatable objects that want to use this
wrapper mechanism. |
public ActivateWrapper(java.rmi.activation.ActivationID id, java.rmi.MarshalledObject data) throws java.lang.Exception
ActivateDesc
from the provided
data
parameter.
ServiceClassLoader
using the import and
export codebases obtained from the provided ActivateDesc
,
SharedActivationPolicyPermission
ServiceClassLoader
and
the corresponding policy file obtained from the ActivateDesc
with the AggregatePolicyProvider
ServiceClassLoader
.
Policy
object, if any, with a
AggregatePolicyProvider
.id
- The ActivationID
of this objectdata
- The activation data for this objectjava.lang.Exception
- of any errors occurServiceClassLoader
,
AggregatePolicyProvider
,
SharedActivationPolicyPermission
,
Policy
public static java.rmi.activation.ActivationID register(java.rmi.activation.ActivationGroupID gid, ActivateWrapper.ActivateDesc desc, boolean restart, java.rmi.activation.ActivationSystem sys) throws java.rmi.activation.ActivationException, java.rmi.RemoteException
Activatable.register()
for activatable objects that want to use this
wrapper mechanism.java.rmi.activation.ActivationException
- if there was a problem registering the
activatable class with the activation systemjava.rmi.RemoteException
- if there was a problem communicating with the
activation system


You can change the indentation of blocks by dragging them over to the right or left inside of the area in which you construct your program. Use the READ FROM INPUT INTO block to see how you can change the tabbing. The READ FROM INPUT INTO block reads input from the console into the variable stated in the block.


The latest breakthrough in single-cell omics is on multi-modal profiling of different biomolecule species in individual cells. Among the fast evolving biotechnologies developed for multi-modal profiling, cellular indexing of transcriptomes and epitopes by sequencing (CITE-seq) is attracting attention, especially in the field of immunology, given its ability to simultaneously quantify global gene expression and cellular proteins using RNA-sequencing and antibody-derived tags (ADTs) on single cells. While the additional protein marker information brought about by ADTs is extremely valuable, new biological insights can only be gained by developing analytic methods that fully take advantage of the complementarity between mRNA and ADT expression measured in CITE-seq.
To address this, we developed a streamlined pipeline–CiteFuse–that consists of a suite of tools for the integration and the downstream analysis of CITE-seq data. In this workshop, we will provide a hands-on experience to the CiteFuse package and cover all the steps including doublet detection, modality integration, cell type clustering, differential RNA and ADT expression analysis, ADT evaluation, and ligand–receptor interaction analysis on a publicly available CITE-seq dataset. We also demonstrate the applicability of CiteFuse package on other multi-modal data types by applying our pipeline on the recently developed ASAP-seq data.
This vignette provides a more complete description of the various tools in CiteFuse and will serve as the basis of our workshop.
Software:
SingleCellExperiment
classBackground reading:
An example for a 55-minute workshop:
| Activity | Time |
|---|---|
| Introduction | 15m |
| Data processing and integration | 15m |
| Downstream analysis | 15m |
| Application of CiteFuse on ASAP-seq | 5m |
| Wrap-up and Conclusions | 5m |


In this demo you see how a custom element can have a method, and how that method can access the containing page DOM. This means Javascript inside of a custom element has full access to the parent page, and is not encapsulated or isolated.
Polymer Element


AnyArrayBuffer
public struct AnyArrayBuffer<Dispatch> where Dispatch : AnyObject
A resizable, value-semantic buffer of homogenous elements of statically-unknown type.
-
Undocumented
Declaration
Swift
public typealias Storage = AnyArrayStorage
-
A bounded contiguous buffer comprising all of
self
‘s storage.Declaration
Swift
public var storage: AnyArrayBuffer<Dispatch>.Storage?
-
A “vtable” of functions implementing type-erased operations that depend on the Element type.
Declaration
Swift
public let dispatch: Dispatch
-
Undocumented
Declaration
Swift
public init<Element>(storage: ArrayStorage<Element>, dispatch: Dispatch)
-
Creates a buffer with elements from
src
.Declaration
Swift
public init(_ src: AnyArrayBuffer)
-
Returns
true
iff an element of typee
can be appended toself
.Declaration
Swift
public func canAppendElement(ofType e: TypeID) -> Bool
-
Returns the result of invoking
body
on a typed alias ofself
, ifself.canStoreElement(ofType: Type<Element>.id)
; returnsnil
otherwise.Declaration
Swift
public mutating func mutate<Element, R>( ifElementType _: Type<Element>, _ body: (_ me: inout ArrayBuffer<Element>)->R ) -> R?
-
Returns the result of invoking
body
on a typed alias ofself
.Requires
self.elementType == Element.self
.Declaration
Swift
@available(*, deprecated, message: "use subscript(unsafelyAssumingElementType:﹚ instead.") public mutating func unsafelyMutate<Element, R>( assumingElementType _: Type<Element>, _ body: (_ me: inout ArrayBuffer<Element>)->R ) -> R
-
Creates an instance containing the same elements as
src
, failing ifsrc
is not dispatched by aDispatch
or a subclass thereof.Declaration
Swift
public init?<OtherDispatch>(_ src: AnyArrayBuffer<OtherDispatch>) where OtherDispatch : AnyObject
-
Creates an instance containing the same elements as
src
.Requires
src.dispatch is Dispatch.Type
.Declaration
Swift
public init<OtherDispatch>(unsafelyCasting src: AnyArrayBuffer<OtherDispatch>) where OtherDispatch : AnyObject
-
The number of stored elements.
Declaration
Swift
public var count: Int { get }
-
The number of elements that can be stored in
self
without reallocation, provided its representation is not shared with other instances.Declaration
Swift
public var capacity: Int { get }
-
Accesses
self
as anArrayBuffer<Element>
ifElement.self == elementType
.- Writing
nil
removes all elements ofself
. - Where
Element.self != elementType
:- reading returns
nil
. - writing changes the type of elements stored in
self
.
- reading returns
Declaration
Swift
public subscript<Element>(elementType _: Type<Element>) -> ArrayBuffer<Element>? { get set }
- Writing
-
Accesses
self
as anArrayBuffer<Element>
.Requires
Element.self == elementType
.Declaration
Swift
public subscript<Element>(existingElementType _: Type<Element>) -> ArrayBuffer<Element> { get set }
-
Accesses
self
as anArrayBuffer<Element>
unsafely assumingElement.self == elementType
.Requires
self.storage!.isUsable(forElementType: Type<Element>)
.Declaration
Swift
public subscript<Element>(unsafelyAssumingElementType _: Type<Element>) -> ArrayBuffer<Element> { get set }
-
Creates an instance containing the same elements as
src
.Declaration
Swift
public init<Element>(_ src: ArrayBuffer<Element>)
-
Creates an instance containing the same elements as
src
.Declaration
Swift
public init<OtherDispatch>(_ src: AnyArrayBuffer<OtherDispatch>) where OtherDispatch : AnyObject


treedable-dynamic:
treetable:
name
area (km²)
America
North America
South America
Argentina
2766890
Bolivia
1098580
Brazil
8511965
Para
1247689
tree:
grid:
ID
Sender
Received
Link
1
1
1
1
2
2
2
2
A
B
C
D
Data:


Chicken Wings w/ Prawn Sauce Fried Calamari French Fries Penang Fried Kuey Teow w/ Chicken Kuey Teow w/ Seafood (Wet or Dry) Kuey Teow w/ Seafood in Egg Sauce Vietnamese Style Beef w/ Rice Black Pepper Chicken w/ Garlic Fried Rice Buttermilk Chicken w/ Garlic Fried Rice Roasted Honey BBQ Chicken Roasted Chicken w/ Fries Roasted Chicken w/ Garlic Fried Rice Ayam Kari Kapitan Nasi Lemak Ayam Nasi Goreng w/ Ayam BBQ Ranch Pepperoni Tuna Marina Baked Spaghetti Bolo (Chicken or Beef) Baked Mac & Cheese Baked Rice w/ PepperoniMenu - Items
Freshco Food Junction
Snacks
Price: $6.00
Price: $5.50
Price: $2.00
Noodles
Price: $5.50
Price: $5.50
Price: $5.50
Rice Dishes
Price: $6.00
Price: $5.90
Price: $5.90
Roasted Chicken
Price: $12.80 Whole
$6.60 Half
Price: $5.00
Price: $5.00
Local Favourites
Price: $5.50
Price: $5.00
Price: $5.90
Pizza
Price: $2.90 per Slice
$20.90 Whole
Price: $2.90 per Slice
$20.90 Whole
Price: $2.90 per Slice
$20.90 Whole
Baked Special
Price: $4.00
Price: $4.00
Price: $4.30


Scots university students in Hong Kong urged to return to the UK amid ongoing protests
The University of Edinburgh has asked that 21 students return to the UK as soon as they as anti-government protests continue to take over Hong Kong.
by Lucinda CameronA Scottish university has recalled students on exchange programmes in Hong Kong as civil unrest continues.
The University of Edinburgh has asked the 21 students affected to return to the UK as soon as they can.
Anti-government protests have been raging in Hong Kong for months, and students and other protesters have taken over major campuses, building barricades and stockpiling petrol bombs and other weapons.
The Chinese University of Hong Kong has suspended classes for the rest of the year, and others have asked students to switch to online learning.
A spokesperson for the University of Edinburgh said: "The suspension of classes at educational institutions in Hong Kong has affected 21 Edinburgh students, who are currently on exchange there.
"We are therefore requesting that all of our students in Hong Kong return to the UK , at their earliest opportunity.
"We are providing advice and support to each affected student to ensure all are in a position to return to the UK."
Last month the University of Edinburgh recalled all nine of its students studying in Egypt, after two were detained by authorities.
They have since been released but the university advised all of its students in the country to return home, citing concerns for their safety.


interface HasManyAssociation<F : ApplicationRecord, T : ApplicationRecord> : MutableCollection<T>, Association
Represents a one-to-many association between models F and T respectively
abstract val collection: MutableList<T> |
|
abstract val fromKlass: KClass<F> |
fun <F : ApplicationRecord, T : ApplicationRecord> empty(): HasManyAssociationImpl<F, T> |
abstract class HasManyAssociationImpl<F : ApplicationRecord, T : ApplicationRecord> : HasManyAssociation<F, T> |


Welcome! This page is a brief introduction to the star of this family, John.
I was born in late 1990 and was the fourth and final additional to the happy family. I attended high school at West Point/Beemer Jr/Sr High and graduated in 2009. From there, I moved to Omaha, NE. I started my educational career at the University of Nebraska at Omaha, but I would begin to bum around the next couple years. It wasn't until the summer of 2012 that I would start studying Management Information Systems. I started as a developer intern at First Data, but now my programming expertise would lead to more lucrative offers.


Crowdsourced mock coding interviews.
Practice your interviewing ability with real interviewers at any time.
Interested? Join our mailing list
Summary of the hack's awesomeness
Some text here hyping up the hack
Some text here explaining the hack
A brief description of one of the best features of the hack.


Normal Mode. Recommended for 99.9% of players. Best experiance.
Extreme Mode. (Original Mode) Only play once you have beaten Normal Mode. Only for advanced players. Far more enemies, traps and no extra reward. Just imposibly hard.
Choose a mode.
click to run original mode


26 In the sixth month of Elizabeth’s pregnancy, God sent the angel Gabriel to Nazareth, a town in Galilee, 27 to a virgin pledged to be married to a man named Joseph, a descendant of David. The virgin’s name was Mary. 28 The angel went to her and said, “Greetings, you who are highly favored! The Lord is with you.” 29 Mary was greatly troubled at his words and wondered what kind of greeting this might be. 30 But the angel said to her, “Do not be afraid, Mary; you have found favor with God. 31 You will conceive and give birth to a son, and you are to call him Jesus. 32 He will be great and will be called the Son of the Most High. The Lord God will give him the throne of his father David, 33 and he will reign over Jacob’s descendants forever; his kingdom will never end.” 34 “How will this be,” Mary asked the angel, “since I am a virgin?” 35 The angel answered, “The Holy Spirit will come on you, and the power of the Most High will overshadow you. So the holy one to be born will be called[a] the Son of God. 36 Even Elizabeth your relative is going to have a child in her old age, and she who was said to be unable to conceive is in her sixth month. 37 For no word from God will ever fail.” 38 “I am the Lord’s servant,” Mary answered. “May your word to me be fulfilled.” Then the angel left her.
39 At that time Mary got ready and hurried to a town in the hill country of Judea, 40 where she entered Zechariah’s home and greeted Elizabeth. 41 When Elizabeth heard Mary’s greeting, the baby leaped in her womb, and Elizabeth was filled with the Holy Spirit. 42 In a loud voice she exclaimed: “Blessed are you among women, and blessed is the child you will bear! 43 But why am I so favored, that the mother of my Lord should come to me? 44 As soon as the sound of your greeting reached my ears, the baby in my womb leaped for joy. 45 Blessed is she who has believed that the Lord would fulfill his promises to her!” 46 And Mary said: “My soul glorifies the Lord 47 and my spirit rejoices in God my Savior, 48 for he has been mindful of the humble state of his servant. From now on all generations will call me blessed, 49 for the Mighty One has done great things for me— holy is his name. 50 His mercy extends to those who fear him, from generation to generation. 51 He has performed mighty deeds with his arm; he has scattered those who are proud in their inmost thoughts. 52 He has brought down rulers from their thrones but has lifted up the humble. 53 He has filled the hungry with good things but has sent the rich away empty. 54 He has helped his servant Israel, remembering to be merciful 55 to Abraham and his descendants forever, just as he promised our ancestors.” 56 Mary stayed with Elizabeth for about three months and then returned home.
18 This is how the birth of Jesus the Messiah came about[a]: His mother Mary was pledged to be married to Joseph, but before they came together, she was found to be pregnant through the Holy Spirit. 19 Because Joseph her husband was faithful to the law, and yet[b] did not want to expose her to public disgrace, he had in mind to divorce her quietly. 20 But after he had considered this, an angel of the Lord appeared to him in a dream and said, “Joseph son of David, do not be afraid to take Mary home as your wife, because what is conceived in her is from the Holy Spirit. 21 She will give birth to a son, and you are to give him the name Jesus,[c] because he will save his people from their sins.” 22 All this took place to fulfill what the Lord had said through the prophet: 23 “The virgin will conceive and give birth to a son, and they will call him Immanuel”[d] (which means “God with us”). 24 When Joseph woke up, he did what the angel of the Lord had commanded him and took Mary home as his wife. 25 But he did not consummate their marriage until she gave birth to a son. And he gave him the name Jesus.
1 In those days Caesar Augustus issued a decree that a census should be taken of the entire Roman world. 2 (This was the first census that took place while[a] Quirinius was governor of Syria.) 3 And everyone went to their own town to register. 4 So Joseph also went up from the town of Nazareth in Galilee to Judea, to Bethlehem the town of David, because he belonged to the house and line of David. 5 He went there to register with Mary, who was pledged to be married to him and was expecting a child. 6 While they were there, the time came for the baby to be born, 7 and she gave birth to her firstborn, a son. She wrapped him in cloths and placed him in a manger, because there was no guest room available for them.
8 And there were shepherds living out in the fields nearby, keeping watch over their flocks at night. 9 An angel of the Lord appeared to them, and the glory of the Lord shone around them, and they were terrified. 10 But the angel said to them, “Do not be afraid. I bring you good news that will cause great joy for all the people. 11 Today in the town of David a Savior has been born to you; he is the Messiah, the Lord. 12 This will be a sign to you: You will find a baby wrapped in cloths and lying in a manger.” 13 Suddenly a great company of the heavenly host appeared with the angel, praising God and saying, 14 “Glory to God in the highest heaven, and on earth peace to those on whom his favor rests.” 15 When the angels had left them and gone into heaven, the shepherds said to one another, “Let’s go to Bethlehem and see this thing that has happened, which the Lord has told us about.” 16 So they hurried off and found Mary and Joseph, and the baby, who was lying in the manger. 17 When they had seen him, they spread the word concerning what had been told them about this child, 18 and all who heard it were amazed at what the shepherds said to them. 19 But Mary treasured up all these things and pondered them in her heart. 20 The shepherds returned, glorifying and praising God for all the things they had heard and seen, which were just as they had been told.
1 After Jesus was born in Bethlehem in Judea, during the time of King Herod, Magi from the east came to Jerusalem 2 and asked, “Where is the one who has been born king of the Jews? We saw his star when it rose and have come to worship him.” 3 When King Herod heard this he was disturbed, and all Jerusalem with him. 4 When he had called together all the people’s chief priests and teachers of the law, he asked them where the Messiah was to be born. 5 “In Bethlehem in Judea,” they replied, “for this is what the prophet has written: 6 “‘But you, Bethlehem, in the land of Judah, are by no means least among the rulers of Judah; for out of you will come a ruler who will shepherd my people Israel.’” 7 Then Herod called the Magi secretly and found out from them the exact time the star had appeared. 8 He sent them to Bethlehem and said, “Go and search carefully for the child. As soon as you find him, report to me, so that I too may go and worship him.” 9 After they had heard the king, they went on their way, and the star they had seen when it rose went ahead of them until it stopped over the place where the child was. 10 When they saw the star, they were overjoyed. 11 On coming to the house, they saw the child with his mother Mary, and they bowed down and worshiped him. Then they opened their treasures and presented him with gifts of gold, frankincense and myrrh. 12 And having been warned in a dream not to go back to Herod, they returned to their country by another route.
13 When they had gone, an angel of the Lord appeared to Joseph in a dream. “Get up,” he said, “take the child and his mother and escape to Egypt.  And so was fulfilled what the Lord had said through the prophet: “Out of Egypt I called my son.” 16 When Herod realized that he had been outwitted by the Magi, he was furious, and he gave orders to kill all the boys in Bethlehem and its vicinity who were two years old and under, in accordance with the time he had learned from the Magi. 17 Then what was said through the prophet Jeremiah was fulfilled: 18 “A voice is heard in Ramah, weeping and great mourning, Rachel weeping for her children and refusing to be comforted, because they are no more.”
19 After Herod died, an angel of the Lord appeared in a dream to Joseph in Egypt 20 and said, “Get up, take the child and his mother and go to the land of Israel, for those who were trying to take the child’s life are dead.” 21 So he got up, took the child and his mother and went to the land of Israel.
New International Version
In courtesy of Bible Gateway ©


{% extends PATH + "/inc/layout.html" %} {% block staff_content %} {# this is a macro: pass the id of the selected iteam. Code in inc/layout.html #} {{ horizontal_nav('nav-cases') }}
| Name | Specialism | Case type | Date submitted | |
|---|---|---|---|---|
| Oliver Reed | Pan disability | New application | 25 May 2018 | View case |
| Mavis Prince | Pan disability | New application | 10:23:12 29 June 2018 | View case |
| Malcolm Rifind | Pan disablity | New application | 13:24:46 12 July 2018 | View case |
| Martin Short | Pan disability | New application | 22:37:21 16 July 2018 | View case |
| Cheryl Cooke | Pan disability | New application | 09:54:23 17 July 2018 | View case |


Discover whether a city is currently a buyer's or seller's market.
Wait until the ideal market temperature. Where would you like to buy/sell?


{% extends "base.html" %} {% load i18n %} {% load crispy_forms_tags %} {% block title %}{% trans "Secure your account" %}{% endblock %} {% block main %}
{% trans "Your recovery codes have been regenerated, and the old ones have been removed from your account." %}
{% trans "They are displayed below, and will be displayed only once. They can be used in situations where you don't have access to your usual authenticator." %}
{% for code in codes %}{{ code }}{% if not forloop.last %} {% endif %}{% endfor %}


Pizza Order Form
Pizza Type:
Please select...
Alpoha Chicken
Beef Pepperoni
Chicken Delight
Deluxe Cheese
Quantity:
Size:
Small
Medium
Large
Crust:
Thin
Thick
Deep Dish
Toppings:
Mushroom
Sausage
Olives
Addons:
Buffalo Wings
Garlic Bread
Total price for your order is $0
Deliver to:
Name:
Address:
Postal Code:
Phone #:
Email:
Date:
Time:
Submit
Reset


Dynamically updated every day, the OONI API enables researchers and data scientists to analyze all data collected from OONI Probes around the world.
Download and search OONI Probe network measurements.
Join the OONI data analyst community and help uncover internet censorship worldwide!
READ THE API DOCS| ASN | Country code | Test Start Time | Test Name | |
|---|---|---|---|---|
| AS{{ report_file.probe_asn }} | {{ report_file.probe_cc }} | {{ report_file.test_start_time }} | {{ report_file.test_name }} | Download |


Core
API Keys
You will need keys to work with the APIs.
- Application ID: Identifies your Application for analytics and quota limits.
- Campus Keys: A Token Key Moniker (TKM), Shared Secret, and Client String identifies the LearningStudio campus where your data comes from.
You can get an Application ID for your app and campus keys for our Sandbox Campus by creating an app on the PDN. Learn more here.
Introduction
LearningStudio Course APIs are REST-based services, and all calls must be authenticated with either an OAuth 1 signature or with an OAuth 2 user token. While not difficult to create your own tools for making these requests, the Core library simplifies the effort by automatically handling authentication.
This library uses the Authentication library, so you need to provide the same configuration information as described there. However, Core will do the heavy lifting of generating and managing signatures and tokens for the requests.
Using Core
Setup
To begin, require the learning_studio_authentication/config
, learning_studio_authentication/service
, and learning_studio_core/basic_service
resources.
require 'learning_studio_authentication/config'
require 'learning_studio_authentication/service'
require 'learning_studio_core/basic_service'
Authentication
You'll need to provide your authentication details (keys, client string, etc) so the Core library can handle authentication. The OAuthConfig
class is a generic carrier for the configuration information for all authentication methods. You'll add the information you need using the following methods.
config = LearningStudioAuthentication::Config::OAuthConfig.new({
:application_name => APP_NAME,
:application_id => APP_ID,
:consumer_key => TOKEN_KEY_MONIKER,
:consumer_secret => SHARED_SECRET,
:client_string => CLIENT_STRING
})
There are differences in what values are needed between the different OAuth methods. Generally, adding all five pieces of information is most flexible, but you can leave out the pieces you don't need. For example, if using OAuth 1 only (System to System calls), you don't need the Application Name or Client String.
The OAuthServiceFactory
object instantiates the appropriate service for the authentication method you want to use. When using core, you only need to create the Factory and pass it to the Core library.
factory = LearningStudioAuthentication::Service::OAuthServiceFactory.new(config)
Requests
Next, you'll instantiate the Core library's BasicService
, which handles all the work of making an API call. When creating the object, pass the OAuth Factory as the only parameter:
basic_service = LearningStudioCore::BasicService.new(factory)
Before making an API call, set the service to the OAuth method you'll use. If using OAuth 2 for a user token, pass the user's username, and if using Password grant type, also send the password.
# OAuth 1
basic_service.use_oauth1()
# OAuth 2 Assertion Grant Type
basic_service.use_oauth2({USERNAME})
# OAuth 2 Assertion Grant Type
basic_service.use_oauth2({USERNAME}, {PASSWORD})
Finally, use the request
method to make the request. This method has the following signature:
request(method, relative_url, body = "", extra_headers = {})
| Parameter | Description |
|---|---|
method |
Any of GET , POST , PUT , or DELETE , depending on the operation you're performing. Required for all requests. |
relativeUrl |
The URI of the API endpoint you're calling; this is only the "path" portion of the request. Required for all requests. Example: /me/courses |
body |
The body of the API request. Required for POST and PUT operations only. |
extra_headers |
A dictionary of any additional headers you need to send with the request. The key should be the header name, and the value the header value. This is used primarily by the other LearningStudio libraries. Example: {'Content-Type': 'application/json'} |
Results
When you call request
, it will return a response
object. This object has these methods:
| Property | Description |
|---|---|
content_type |
The type of response, either JSON or XML if it's text-based, or the MIME type of the content if binary content. |
content |
The text-based body of the response from the API. It is returned as a string of either JSON or XML , and is not parsed into a native object. |
binary_content |
The binary-based body of the response from the API. |
is_binary |
Returns either true or false as to whether the body of the API response is binary data (for example, if downloading a document or threaded discussion attachment). |
| About the API Request | |
headers |
The headers used in the request. |
method |
The HTTP method that was used. |
status_code |
The HTTP Status Code from the API request. Example:200 , 201 , 400 , etc. |
status_message |
The HTTP Status message from the API request. Example:Created or Not Found . |
url |
The URL that was called to make the request. |
error |
Either true or false as to whether there was a problem with the API request. |
Example
require 'learning_studio_authentication/config'
require 'learning_studio_authentication/service'
require 'learning_studio_core/basic_service'
APP_ID = "" # Identifies your Application
APP_NAME = "" # No spaces for best results (e.g., MyAppName)
TOKEN_KEY_MONIKER = ""
SHARED_SECRET = ""
CLIENT_STRING = "" # Identifies the LearningStudio instance
USERNAME = "" # Provided by user through a sign-in box
API_URI = "" # e.g., /me
config = LearningStudioAuthentication::Config::OAuthConfig.new({
:application_name => APP_NAME,
:application_id => APP_ID,
:consumer_key => TOKEN_KEY_MONIKER,
:consumer_secret => SHARED_SECRET,
:client_string => CLIENT_STRING
})
factory = LearningStudioAuthentication::Service::OAuthServiceFactory.new(config)
basic_service = LearningStudioCore::BasicService.new(factory)
basic_service.use_oauth2(USERNAME)
begin
response = basic_service.request('GET', API_URI)
if response.error?
puts "%s : %s" % [response.status_code, response.status_message] # 404 : Not Found
else
puts "%s : %s" % [response.content_type, response.content] # application/json : { ... }
end
rescue Exception => e
puts "Exception from request calling '%s': %s" % [API_URI, e.message]
end


Access
Open to all members,free for members
Create Store
Through Mysite or Marketplace
Visibility
Limited - only to private community of the store owner
Features
All Store elements enabled but visiblity limited to private circles.
Store Listing
Listed under 250 plus sub-categories
Streaming
Closed users, private Community
Ads & Campaigns feature
Link to Ads & Campaigns for streaming for eg special deals, new product launch etc.,
Pricing of Stores
Transaction fee per transaction for using the payment gateway services. Logistics, Packaging, Frieght & other charges are not included
Access
Open to all members
Create Store
Through Mysite or Marketplace
Visibility
Unlimited
Features
All store elements enabled
Store Listing
Listed under 250 plus sub-categories
Streaming
Closed users, private Community
Ads & Campaigns feature
Link to Ads & Campaigns for streaming for eg special deals, new product launch etc.,
Pricing of Stores
Fixed price, Rs.24000 per annum ( limted to Rs.5Lac per annum revenue) Payment Gateway charges are additional, Logistics, Packaging, Frieght & other charges are not included
Access
Open to all members and non members who want to purchase this option.
Create Store
Through Marketplace with customised admin controls and offline intervention
Visibility
Unlimited Visibility like Paid standard, in addition customised priority on Evezown, MarketPlace landing pages.
Features
All store elements enabled , in addition customisation and add-ons can be done as per requirement,for eg. Visual presentation, analytics, promotion & branding can be enhanced
Store Listing
Listed under 250 plus sub-categories,special sub category can be created if required to improve searchability.
Streaming
Standard promotion features plus additional customised web pomotional features as per requirement of the category, subcategory
Ads & Campaigns feature
Paid Store features plus additional customised branding and marketing features as per requirement
Pricing of Stores
Custom Pricing based on member requirement specification, would be quoted offline


Validation Summary
You have successfully validated your file.
Please review the Respondent and File information below. Your validated file or any data related to the validation process will not be submitted or uploaded at this time.
Respondent Information
- Name
- {{transmittalSheet.institutionName}}
- Respondent ID
- {{transmittalSheet.respondentID}}
- Tax ID
- {{transmittalSheet.taxID}}
- Agency
- {{transmittalSheet.agencyCode | agency}}
- Contact Name
- {{transmittalSheet.contactName}}
- Phone Number
- {{transmittalSheet.contactPhone}}
- Email Address
- {{transmittalSheet.respondentEmail}}
File Information
- File Name
- {{fileMetadata.filename}}
- Reporting Year
- {{transmittalSheet.activityYear}}
- Total Loans/Applications
- {{transmittalSheet.totalLineEntries}}