An easy-to-use platform for EEG experimentation in the classroom
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

update some style suggestions from linting

+39 -49
+14 -17
app/components/AnalyzeComponent.js
··· 9 9 Divider, 10 10 Button, 11 11 Checkbox, 12 - Transition, 13 - Container, 14 12 Sidebar 15 13 } from 'semantic-ui-react'; 16 14 import { isNil } from 'lodash'; ··· 109 107 removeOutliers: false, 110 108 showDataPoints: false, 111 109 isSidebarVisible: false, 112 - displayOutlierVisible: false, 110 + // displayOutlierVisible: false, 113 111 displayMode: 'datapoints', 114 112 helpMode: 'datapoints', 115 113 selectedFilePaths: [], ··· 180 178 this.setState({ 181 179 selectedFilePaths: data.value, 182 180 selectedSubjects: getSubjectNamesFromFiles(data.value), 183 - dataToPlot: dataToPlot, 184 - layout: layout 181 + dataToPlot, 182 + layout 185 183 }); 186 184 } 187 185 ··· 208 206 ); 209 207 this.setState({ 210 208 selectedDependentVariable: data.value, 211 - dataToPlot: dataToPlot, 212 - layout: layout 209 + dataToPlot, 210 + layout 213 211 }); 214 212 } 215 213 ··· 223 221 ); 224 222 this.setState({ 225 223 removeOutliers: !this.state.removeOutliers, 226 - dataToPlot: dataToPlot, 227 - layout: layout, 224 + dataToPlot, 225 + layout, 228 226 helpMode: 'outliers' 229 227 }); 230 228 } ··· 239 237 ); 240 238 this.setState({ 241 239 showDataPoints: !this.state.showDataPoints, 242 - dataToPlot: dataToPlot, 243 - layout: layout 240 + dataToPlot, 241 + layout 244 242 }); 245 243 } 246 244 ··· 254 252 displayMode 255 253 ); 256 254 this.setState({ 257 - dataToPlot: dataToPlot, 258 - layout: layout, 259 - displayMode: displayMode, 255 + dataToPlot, 256 + layout, 257 + displayMode, 260 258 helpMode: displayMode, 261 259 }); 262 260 } ··· 538 536 toggle 539 537 active={this.state.displayMode === 'whiskers'} 540 538 onClick={()=> this.handleDisplayModeChange('whiskers')} 541 - > 542 - Box Plot 539 + > 540 + Box Plot 543 541 </Button> 544 - 545 542 </Button.Group> 546 543 547 544 <Button
+25 -32
app/utils/behavior/compute.js
··· 28 28 return { 29 29 subject: e.map(r => r.subject)[0], 30 30 session: e.map(r => r.session)[0], 31 - ['RT_' + conditions[0]]: rtMean[conditions[0]], 32 - ['RT_' + conditions[1]]: rtMean[conditions[1]], 33 - ['Accuracy_' + conditions[0]]: accuracyPercent[conditions[0]], 34 - ['Accuracy_' + conditions[1]]: accuracyPercent[conditions[1]], 31 + [`RT_${conditions[0]}`]: rtMean[conditions[0]], 32 + [`RT_${conditions[1]}`]: rtMean[conditions[1]], 33 + [`Accuracy_${conditions[0]}`]: accuracyPercent[conditions[0]], 34 + [`Accuracy_${conditions[1]}`]: accuracyPercent[conditions[1]], 35 35 response_given: 'yes', 36 36 correct_response: 'true' 37 37 } ··· 44 44 const processedData = data.map(result => { 45 45 if (result.meta.datafile.split('/').pop().includes('aggregated')){ 46 46 return transformAggregated(result) 47 - } else { 48 - return filterData(result, removeOutliers) 49 47 } 48 + return filterData(result, removeOutliers) 49 + 50 50 }); 51 51 const colors = ['#28619E','#3DBBDB']; 52 52 const conditions = [... new Set(processedData[0].map(row => row.condition))]; ··· 62 62 63 63 const transformAggregated = (result) => { 64 64 const conditions = result.meta.fields.filter(field => field.startsWith('RT_')).map(c => c.split('RT_')[1]); 65 - const transformed = conditions.map((condition,i) => { 66 - return result.data.map(e => { 67 - return { 65 + const transformed = conditions.map((condition) => result.data.map(e => ({ 68 66 reaction_time: parseFloat(e[`RT_${condition}`]), 69 67 subject: result.meta.datafile.split('/').pop().split('.csv')[0], 70 - condition: condition, 68 + condition, 71 69 session: e.session, 72 70 accuracy: parseFloat(e[`Accuracy_${condition}`]), 73 71 response_given: e.response_given, 74 72 correct_response: e.correct_response 75 - } 76 - }) 77 - }); 73 + }))); 78 74 const data = transformed.reduce( (acc, item) => acc.concat(item), []); 79 75 return data 80 76 } ··· 82 78 const filterData = (data, removeOutliers) => { 83 79 let filteredData = data.data 84 80 .filter(row => row.trial_number) 85 - .map(row => { 86 - return { 81 + .map(row => ({ 87 82 condition: row.condition, 88 83 subject: data.meta.datafile.split('/').pop().split('-')[0], 89 84 session: data.meta.datafile.split('/').pop().split('-')[1], ··· 91 86 correct_response: row.correct_response, 92 87 trial_number: row.trial_number, 93 88 response_given: row.response_given 94 - } 95 - }) 89 + })) 96 90 // .filter(row => row.reaction_time > 0 && row.correct) 97 91 if(removeOutliers){ 98 92 const mean = ss.mean(filteredData.filter(r => r.response_given === 'yes' && r.correct_response === 'true').map(r => r.reaction_time)); ··· 105 99 } 106 100 107 101 const computeRT = (data, dependentVariable, conditions, showDataPoints, colors, displayMode) => { 108 - let dataToPlot, maxValue = 0; 102 + let dataToPlot = 0; 103 + let maxValue = 0; 109 104 switch (displayMode) { 110 105 case "datapoints": 111 106 default: ··· 118 113 const x = xRaw.map(x => (subjects.indexOf(x) + 1 + i/4 + (Math.random() - 0.5)/5 )); 119 114 tickValuesX = subjects.map(x => subjects.indexOf(x) + 1 + 1/8); 120 115 tickTextX = subjects; 121 - obj[condition] = { x: x, y: y }; 116 + obj[condition] = { x, y }; 122 117 return obj; 123 118 }, {}) 124 119 dataToPlot['tickvals'] = tickValuesX; ··· 129 124 130 125 case "errorbars": 131 126 let maxValueSE = 0; 132 - dataToPlot = conditions.reduce((obj, condition, i) => { 127 + dataToPlot = conditions.reduce((obj, condition) => { 133 128 const xRaw = data.reduce((a, b) => a.concat(b), []).filter(r => r.response_given === 'yes' && r.correct_response === 'true').filter(e => e.condition === condition).map(r => r.subject); 134 129 const x = Array.from(new Set(xRaw)) 135 130 const data_condition = data.map(d => d.filter(r => r.response_given === 'yes' && r.correct_response === 'true').filter(e => e.condition == condition)); 136 131 const y_bars_prep = x.map( 137 132 a => data_condition.map( 138 - d => {return d.filter(e => e.subject === a)} 133 + d => d.filter(e => e.subject === a) 139 134 ).filter(d => d.length > 0) 140 135 ); 141 136 const y = y_bars_prep.map(y => ss.mean(y.reduce((a, b) => a.concat(b), []).map(r => r.reaction_time))); 142 137 maxValue = Math.max(...y) > maxValue ? Math.max(...y) : maxValue; 143 - const stErrorFunction = (array) => {return ss.sampleStandardDeviation(array) / Math.sqrt(array.length)}; 138 + const stErrorFunction = (array) => ss.sampleStandardDeviation(array) / Math.sqrt(array.length); 144 139 const stErrors = data_condition.map(a => a.length > 1 ? stErrorFunction(a.map(r => r.reaction_time)) : 0); 145 140 maxValueSE = Math.max(...stErrors) > maxValueSE ? Math.max(...stErrors) : maxValueSE; 146 - obj[condition] = { x: x, y: y, stErrors: stErrors }; 141 + obj[condition] = { x, y, stErrors }; 147 142 return obj; 148 143 }, {}) 149 144 dataToPlot['lowerLimit'] = 0; ··· 155 150 const x = data.reduce((a, b) => a.concat(b), []).filter(r => r.response_given === 'yes' && r.correct_response === 'true').filter(e => e.condition === condition).map(r => r.subject); 156 151 const y = data.reduce((a, b) => a.concat(b), []).filter(r => r.response_given === 'yes' && r.correct_response === 'true').filter(e => e.condition === condition).map(r => r.reaction_time); 157 152 maxValue = Math.max(...y) > maxValue ? Math.max(...y) : maxValue; 158 - obj[condition] = { x: x, y: y }; 153 + obj[condition] = { x, y }; 159 154 return obj; 160 155 }, {}) 161 156 dataToPlot['lowerLimit'] = 0; ··· 194 189 const x = xRaw.map(x => (subjects.indexOf(x) + 1 + i/4 + (Math.random() - 0.5)/5 )); 195 190 tickValuesX = subjects.map(x => subjects.indexOf(x) + 1 + 1/8); 196 191 tickTextX = subjects; 197 - obj[condition] = { x: x, y: y }; 192 + obj[condition] = { x, y }; 198 193 return obj; 199 194 }, {}) 200 195 dataToPlot['tickvals'] = tickValuesX; ··· 208 203 const correctDataForCondition = data.map(d => d.filter(e => e.condition == condition)); 209 204 const transformedData = correctDataForCondition.map(d => { 210 205 if(d.filter(l => l.accuracy).length > 0){ 211 - return d.map(l => { 212 - return ({ 206 + return d.map(l => ({ 213 207 accuracy: l.accuracy, 214 208 subject: l.subject, 215 - }) 216 - }) 209 + })) 217 210 } else { 218 211 const c = d.filter(e => e.response_given === 'yes' && e.correct_response === 'true'); 219 212 return ({ ··· 226 219 const y = subjects.map( 227 220 subject => ss.mean(transformedData.filter(e => e.subject === subject).map(d => d.accuracy)) 228 221 ); 229 - const stErrorFunction = (array) => {return ss.sampleStandardDeviation(array) / Math.sqrt(array.length)}; 222 + const stErrorFunction = (array) => ss.sampleStandardDeviation(array) / Math.sqrt(array.length); 230 223 const stErrors = subjects.map(subject => { 231 224 let array = transformedData.filter(e => e.subject === subject).map(d => d.accuracy); 232 225 if(array.length > 1){ ··· 235 228 return 0; 236 229 } 237 230 }) 238 - obj[condition] = { x: subjects, y: y, stErrors: stErrors }; 231 + obj[condition] = { x: subjects, y, stErrors }; 239 232 return obj; 240 233 }, {}) 241 234 dataToPlot['lowerLimit'] = 0; ··· 260 253 return d.map(r => r.subject)[0] 261 254 } 262 255 }).reduce( (acc, item) => acc.concat(item), []); 263 - obj[condition] = { x: xRaw, y: y }; 256 + obj[condition] = { x: xRaw, y }; 264 257 return obj; 265 258 }, {}) 266 259 dataToPlot['lowerLimit'] = 0;