scripts/experiment-properties/data/data_controller.js
import {CUSTOM_TRIAL_STRUCTURE_CONDITIONS, get_subconditions} from "/scripts/experiment-properties/data/custom_subcondition_generator.js";
import {JND_BASE, JND_CONDITIONS} from "/scripts/experiment-properties/data/constants/jnd_data.js";
import {STEVENS_BASE, STEVENS_CONDITIONS} from "/scripts/experiment-properties/data/constants/stevens_data.js";
import {ESTIMATION_CONDITIONS} from "/scripts/experiment-properties/data/constants/estimation_data.js";
import {JND_RADIUS_BASE, JND_RADIUS_CONDITIONS} from "/scripts/experiment-properties/data/constants/jnd_radius_data.js";
import {NUMEROSITY_BASE, NUMEROSITY_CONDITIONS} from "/scripts/experiment-properties/data/constants/numerosity_data.js";
import {VISUAL_SEARCH_BASE, VISUAL_SEARCH_CONDITIONS} from "/scripts/experiment-properties/data/constants/visual_search_data.js";
export { get_data,
get_data_subset,
create_condition_dataset,
EXPERIMENT_BASES,
EXPERIMENT_CONDITIONS };
const EXPERIMENT_BASES = {
"JND" : JND_BASE,
"Stevens" : STEVENS_BASE,
"JND_Radius" : JND_RADIUS_BASE,
"Estimation" : [],
"Numerosity" : NUMEROSITY_BASE,
"Visual_Search" : VISUAL_SEARCH_BASE
};
const EXPERIMENT_CONDITIONS = {
"JND" : JND_CONDITIONS,
"Stevens" : STEVENS_CONDITIONS,
"JND_Radius" : JND_RADIUS_CONDITIONS,
"Estimation" : ESTIMATION_CONDITIONS,
"Numerosity" : NUMEROSITY_CONDITIONS,
"Visual_Search" : VISUAL_SEARCH_CONDITIONS,
};
/**
* Retrieves the data for the corresponding experiment object.
*
* @param experiment {object} Model object of the experiment
*
* @return dataset [{assoc}, {assoc}, .... ]
*/
function get_data(experiment){
var dataset;
var trial_structure = experiment.trial_structure;
var graph_type = experiment.graph_type;
var condition = experiment.condition_name;
var experiment_name = experiment.constructor.name;
// Estimation does not have any BASE
if (experiment_name === "Estimation"){
dataset = EXPERIMENT_CONDITIONS["Estimation"][condition];
console.log("LENGTH: " + dataset.length);
}
// If there is a "custom" condition AKA the subconditions are
// generated by code rather than by constants (arrays in the constants folder)
else if (trial_structure === "custom" || CUSTOM_TRIAL_STRUCTURE_CONDITIONS[trial_structure].includes(condition)) {
dataset = get_subconditions(experiment);
}
else {
// If not a base condition
if (!condition.split("_").includes("base")){
// Check that a condition exists
if (!EXPERIMENT_CONDITIONS[experiment_name][condition] || !EXPERIMENT_BASES[experiment_name][trial_structure]){
throw new Error (condition + " is not supported.");
}
// Get subconditions then append to the base
let subconditions = EXPERIMENT_CONDITIONS[experiment_name][condition];
dataset = create_condition_dataset(EXPERIMENT_BASES[experiment_name][trial_structure], subconditions);
// If a base condition
} else {
if (!EXPERIMENT_BASES[experiment_name][trial_structure]) {
throw new Error ("Base for " + condition + " does not exist.");
}
dataset = EXPERIMENT_BASES[experiment_name][trial_structure];
}
}
check_dataset(experiment_name, graph_type, dataset)
return dataset;
}
/**
* Checks if all subconditions have the necessary attributes to run the experiment.
*
* @param experiment {string} type of experiment
* graph_type. {string} type of graph
* dataset {array of JS objects} dataset to check
*/
function check_dataset(experiment_name, graph_type, dataset) {
let name = "";
let graph_attributes = GRAPH_TYPES[graph_type]["attributes"];
let exp_attributes = EXPERIMENTS[experiment_name.toLowerCase()]["attributes"];
let all_attributes = Object.assign({}, graph_attributes);
all_attributes = Object.assign(all_attributes, exp_attributes);
for (let subcondition of dataset) {
// Check that each subcond has the necessary attributes to run the experiment
for (let attribute_key in EXPERIMENTS[experiment_name.toLowerCase()]["attributes"]){
let attribute = EXPERIMENTS[experiment_name.toLowerCase()]["attributes"][attribute_key];
// Check that conditions has all required attributes
if (subcondition[attribute_key] === undefined && attribute["required"]){
throw new Error("Required attribute " + attribute_key + " was not found in the subcondition " + JSON.stringify(subcondition));
}
}
for (let subcondition_key in subcondition) {
// Check that all attributes have been defined in either experiment or graphing config
if (all_attributes[subcondition_key] === undefined) {
throw new Error("Attribute " + subcondition_key + " has not been defined in config files.");
}
// Check that if there is a valid_input, it is listed in the configs
if (Array.isArray(subcondition[subcondition_key])) { //If array, loop through values and check each
for (let value of subcondition[subcondition_key]) {
if (all_attributes[subcondition_key].valid_inputs
&& !all_attributes[subcondition_key].valid_inputs.includes(value)){
throw new Error("Attribute " + subcondition_key + " has value " + value + " that is not a valid value. Valid values are: " + all_attributes[subcondition_key].valid_inputs);
}
}
} else {
if (all_attributes[subcondition_key].valid_inputs
&& !all_attributes[subcondition_key].valid_inputs.includes(subcondition[subcondition_key])){
throw new Error("Attribute " + subcondition_key + " has value " + subcondition[subcondition_key] + " that is not a valid value. Valid values are: " + all_attributes[subcondition_key].valid_inputs);
}
}
}
}
}
/**
* Retrieves a smaller dataset (4 subconditions) given experiment, trial structure and condition.
*
* @param experiment {string} "jnd", "stevens", etc.
* trial_structure {string} "foundational", "design", etc.
* condition {string} Name of condition
*
* @return dataset [{assoc}, {assoc}, .... ]
*/
function get_data_subset(experiment, trial_structure, condition) {
var dataset = get_data(experiment, trial_structure, condition);
return dataset.slice(0, 4);
}
/**
* Appends condition-specific data to the dataset.
*
* @param base_data [{assoc}, {assoc}, .... ] dataset with base experiment constants
* @param condition_data [{assoc}, {assoc}, .... ] condition set for that experiment
*
* @return dataset [{assoc}, {assoc}, .... ]
**/
function create_condition_dataset(base_data, condition_data){
var condition_dataset = [];
if (base_data.length != condition_data.length) {
throw Error("Base dataset length is not equal to condition dataset length.");
}
for (let i in base_data) {
let obj = Object.assign({}, base_data[i], condition_data[i]);
condition_dataset.push(obj);
}
return condition_dataset;
}