diff --git a/conda/js/src/components/experiment/ExperimentEditor.jsx b/conda/js/src/components/experiment/ExperimentEditor.jsx
index 0d9221b3968e34db72804f635818df0c0a28275f..78f3e502588f2e4468686f34b64f534d82757b90 100644
--- a/conda/js/src/components/experiment/ExperimentEditor.jsx
+++ b/conda/js/src/components/experiment/ExperimentEditor.jsx
@@ -588,7 +588,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
 
 						//Object.keys(this.props.data.contents.datasets).map(dsName
 						const newDs = JSON.parse(str);
-						console.log(newDs);
+						//console.log(newDs);
 						this.setContents({...this.props.data.contents, datasets: newDs});
 						for(const dataset in this.props.data.contents.datasets){
 							this.setLockMap(dataset, true);
@@ -719,6 +719,21 @@ export class ExperimentEditor extends React.Component<Props, State> {
 		</FormGroup>
 	);
 
+	// update a block's data (and the globals object, if it changed)
+	updateBlock = (blockName: string, isAnalyzer: boolean, newBlock: any, globals: any = this.props.data.contents.globals) => {
+		if(isAnalyzer)
+			delete newBlock.outputs;
+
+		const bKey = isAnalyzer ? 'analyzers' : 'blocks';
+		const newBlocks = copyObj(this.props.data.contents[bKey]);
+		newBlocks[blockName] = newBlock;
+		this.setContents({
+			...this.props.data.contents,
+			[bKey]: newBlocks,
+			globals,
+		});
+	}
+
 	// renders the currently selected block to edit, if any
 	renderBlock = (blockName: string, block: any, isAnalyzer: boolean, key: number) => {
 		// gets the block info from the tc
@@ -742,19 +757,8 @@ export class ExperimentEditor extends React.Component<Props, State> {
 		});
 
 		// func to update the exp's block info
-		const updateBlock = (newBlock, globals = this.props.data.contents.globals, newName = blockName) => {
-			if(isAnalyzer)
-				delete newBlock.outputs;
-
-			const bKey = isAnalyzer ? 'analyzers' : 'blocks';
-			const newBlocks = changeObjFieldName(this.props.data.contents[bKey], blockName, newName);
-			newBlocks[newName] = newBlock;
-			this.setContents({
-				...this.props.data.contents,
-				[bKey]: newBlocks,
-				globals,
-			});
-		};
+		const updateBlock = (newBlock: any, globals: any = this.props.data.contents.globals) =>
+			this.updateBlock(blockName, isAnalyzer, newBlock, globals);
 
 		// get info that could be from the block or from the global settings
 		const envInfo = block.environment || this.props.data.contents.globals.environment;
@@ -834,69 +838,112 @@ export class ExperimentEditor extends React.Component<Props, State> {
 					<Label>
 						Algorithm
 					</Label>
-					<Input
-						type='select'
-						className='custom-select'
-						valid={block.algorithm !== ''}
-						value={block.algorithm}
-						onChange={e => {
-							// user selected a different algorithm
-							const str = e.target.value;
-							// find the alg or use a dummy algorithm instead
-							const alg = algorithms.find(nb => nb.name === str) || {name: '', contents: {groups: []}};
-							const [ inputs, outputs ] = algIOs(alg);
-							// try to map the IOs from the algorithm to the block via names
-							const findCloseIOMatch = (s: string, arr: string[]): string => {
-								if(arr.length === 1)
-									return arr[0];
-								const findRes = arr.find(str => str.includes(s));
-								if(findRes !== undefined)
-									return findRes;
-								return '';
-							};
-
-							// create the new block obj with the new alg
-							const thisBlock = {
-								...block,
-								algorithm: str,
-							};
-							// assign new inputs
-							if(tcBlock.inputs)
-								thisBlock.inputs = levMapStrings(Object.keys(inputs), tcBlock.inputs);
-							// assign new outputs
-							if(tcBlock.outputs)
-								thisBlock.outputs = levMapStrings(Object.keys(outputs), tcBlock.outputs);
-
-							// setup the parameters (erase & create stuff)
-							const globals = {
-								...this.props.data.contents.globals,
-							};
-							if(alg.contents.parameters && Object.keys(alg.contents.parameters).length > 0)
-								globals[alg.name] = {
-									...Object.entries(alg.contents.parameters || {})
-									.map(([pName, param]) => ({[pName]: getDefaultParameterValue(param)}))
-									.reduce((o, p) => ({...o, ...p}), {}),
-									...this.props.data.contents.globals[alg.name],
-								};
+					<FormGroup row>
+						<Col>
+							<Input
+								type='select'
+								className='custom-select'
+								valid={block.algorithm !== ''}
+								value={block.algorithm}
+								onChange={e => {
+									// user selected a different algorithm
+									const str = e.target.value;
+									// find the alg or use a dummy algorithm instead
+									const alg = algorithms.find(nb => nb.name === str) || {name: '', contents: {groups: []}};
+									const [ inputs, outputs ] = algIOs(alg);
+									// try to map the IOs from the algorithm to the block via names
+									const findCloseIOMatch = (s: string, arr: string[]): string => {
+										if(arr.length === 1)
+											return arr[0];
+										const findRes = arr.find(str => str.includes(s));
+										if(findRes !== undefined)
+											return findRes;
+										return '';
+									};
+
+									// create the new block obj with the new alg
+									const thisBlock = {
+										...block,
+										algorithm: str,
+									};
+									// assign new inputs
+									if(tcBlock.inputs)
+										thisBlock.inputs = levMapStrings(Object.keys(inputs), tcBlock.inputs);
+									// assign new outputs
+									if(tcBlock.outputs)
+										thisBlock.outputs = levMapStrings(Object.keys(outputs), tcBlock.outputs);
+
+									// setup the parameters (erase & create stuff)
+									const globals = copyObj(this.props.data.contents.globals);
+									// if the new alg has parameters, gen the global defaults for the params
+									if(alg.contents.parameters && Object.keys(alg.contents.parameters).length > 0)
+										globals[alg.name] = {
+											...Object.entries(alg.contents.parameters || {})
+											.map(([pName, param]) => ({[pName]: getDefaultParameterValue(param)}))
+											.reduce((o, p) => ({...o, ...p}), {}),
+											...this.props.data.contents.globals[alg.name],
+										};
 
-							if(globals.hasOwnProperty(block.algorithm) &&
-								[...this.props.toolchain.contents.analyzers, ...this.props.toolchain.contents.blocks]
-								.filter(b => b.algorithm === block.algorithm).length <= 1)
-								delete globals[block.algorithm];
+									// if the old algorithm had parameters and no other block is using that alg,
+									// delete the global param defaults for the old alg
+									if(globals.hasOwnProperty(block.algorithm) &&
+										[...this.props.toolchain.contents.analyzers, ...this.props.toolchain.contents.blocks]
+										.filter(b => b.algorithm === block.algorithm).length <= 1)
+										delete globals[block.algorithm];
 
-							updateBlock(thisBlock, globals);
-							this.setLockMap(blockName, true);
-						}}
-					>
-						<option value=''>Algorithm...</option>
-						{
-							possibleAlgorithms
-							.map(nb => nb.name)
-							.map((str, i) =>
-								<option key={i} value={str}>{ str }</option>
-							)
+									updateBlock(thisBlock, globals);
+									this.setLockMap(blockName, true);
+								}}
+							>
+								<option value=''>Algorithm...</option>
+								{
+									possibleAlgorithms
+									.map(nb => nb.name)
+									.map((str, i) =>
+										<option key={i} value={str}>{ str }</option>
+									)
+								}
+							</Input>
+						</Col>
+						{ !isAnalyzer &&
+								<Col sm='auto'>
+									<Button
+										color='primary'
+										disabled={block.algorithm === ''}
+										title={`Copies the algorithm & IO mappings to all unconfigured blocks with the same inputs & outputs`}
+										onClick={() => {
+											// copy the algorithm and input/output mappings to blocks
+											// that are the same except for the block name and dont have an algorithm assigned already
+											const targetBlocks = this.props.toolchain.contents.blocks
+											// not the block being copied from
+											.filter(b => b.name !== blockName)
+											// same IO
+											.filter(b => JSON.stringify(b.inputs) === JSON.stringify(tcBlock.inputs))
+											.filter(b => JSON.stringify(b.outputs) === JSON.stringify(tcBlock.outputs))
+											.map(b => b.name)
+											;
+											//console.log(targetBlocks);
+
+											// because the target blocks have the exact same inputs/outputs as the current block
+											// we dont need to re-compute the block object that we will copy!
+											// instead, just reuse the current block object and assign it to all
+											// the target blocks.
+											// also, because all these blocks are the same algorithm as the current block
+											// we dont need to mess with the globals.
+
+											const newBlocks = copyObj(this.props.data.contents.blocks);
+											targetBlocks.forEach(bName => { newBlocks[bName] = copyObj(block); });
+											this.setContents({
+												...this.props.data.contents,
+												blocks: newBlocks,
+											});
+										}}
+									>
+										Copy to similar blocks
+									</Button>
+								</Col>
 						}
-					</Input>
+					</FormGroup>
 				</FormGroup>
 				{ Object.entries(alg.contents.parameters || {}).length > 0 && <h5>Parameters</h5> }
 				{
diff --git a/conda/js/src/components/experiment/ExperimentEditor.spec.jsx b/conda/js/src/components/experiment/ExperimentEditor.spec.jsx
index c86c65546b6a74ca69a2f8133e8380b0bd91436a..07713901d239510ff54e180c7918c4a21550262b 100644
--- a/conda/js/src/components/experiment/ExperimentEditor.spec.jsx
+++ b/conda/js/src/components/experiment/ExperimentEditor.spec.jsx
@@ -80,7 +80,7 @@ describe('<ExperimentEditor />', () => {
 			const tc = testTcs.find(tc => expName.includes(tc.name));
 			wrapper = mount(
 				<C
-					data={getValidObj({name: expName, contents: {}}, tc, [normalBlocks, ...analyzerBlocks])}
+					data={getValidObj({name: expName, contents: {}}, tc, [...normalBlocks, ...analyzerBlocks])}
 					experiments={[]}
 					normalBlocks={normalBlocks}
 					analyzerBlocks={analyzerBlocks}
@@ -207,5 +207,306 @@ describe('<ExperimentEditor />', () => {
 				}
 			});
 		});
+
+		// tests:
+		// - assigning protocol for datasets
+		// - copy block algs
+		it('test/test/iris_advanced/1/iris', () => {
+			const expName ='test/test/iris_advanced/1/iris';
+			const saveFunc = sinon.spy();
+			const _updateFunc = (obj) => {
+				wrapper.setProps && wrapper.setProps({ data: obj });
+			};
+			const updateFunc = sinon.spy(_updateFunc);
+			const tc = testTcs.find(tc => expName.includes(tc.name));
+			wrapper = mount(
+				<C
+					data={getValidObj({name: expName, contents: {}}, tc, [...normalBlocks, ...analyzerBlocks])}
+					experiments={[]}
+					normalBlocks={normalBlocks}
+					analyzerBlocks={analyzerBlocks}
+					datasets={datasets}
+					toolchain={tc}
+					saveFunc={saveFunc}
+					environments={envs}
+					updateFunc={updateFunc}
+				/>
+			);
+
+			expect(wrapper.props().data).to.have.property('name', expName);
+
+			console.log('doing dataset');
+
+			wrapper.find('div.datasets select').at(0).simulate('change', { target: { value: '{"testing_data":{"database":"iris/1","protocol":"Main","set":"training"},"training_data":{"database":"iris/1","protocol":"Main","set":"testing"}}'}});
+			expect(updateFunc.callCount).to.equal(1);
+			expect(wrapper.props().data.contents).to.have.deep.property('datasets', {
+				'testing_data': {
+					'database': 'iris/1',
+					'protocol': 'Main',
+					'set': 'training'
+				},
+				'training_data': {
+					'database': 'iris/1',
+					'protocol': 'Main',
+					'set': 'testing'
+				}
+			});
+
+			//console.log('finished dataset, doing preprocessor blocks');
+
+			wrapper.find('svg #block_pre_training').simulate('click');
+			expect(wrapper.find({ name: 'pre_training', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted');
+			wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_preprocessor/1'}});
+			//console.log('finished preprocessor_training, copying alg to other preprocessors');
+			expect(updateFunc.callCount).to.equal(2);
+			wrapper.find('div.block0 div.algorithm button').at(0).simulate('click');
+			expect(updateFunc.callCount).to.equal(3);
+
+			expect(wrapper.props().data.contents).to.have.deep.property('blocks', {
+				'pre_testing': {
+					'algorithm': 'test/iris_preprocessor/1',
+					'inputs': {
+						'measurements': 'measurements'
+					},
+					'outputs': {
+						'measurements': 'measurements'
+					},
+					'parameters': {}
+				},
+				'pre_training': {
+					'algorithm': 'test/iris_preprocessor/1',
+					'inputs': {
+						'measurements': 'measurements'
+					},
+					'outputs': {
+						'measurements': 'measurements'
+					},
+					'parameters': {}
+				},
+				'testing_alg': {
+					'algorithm': '',
+					'inputs': {
+						'lda_machine': '',
+						'measurements': ''
+					},
+					'outputs': {
+						'scores': ''
+					},
+					'parameters': {}
+				},
+				'training_alg': {
+					'algorithm': '',
+					'inputs': {
+						'measurements': '',
+						'species': ''
+					},
+					'outputs': {
+						'lda_machine': ''
+					},
+					'parameters': {}
+				}
+			});
+
+			//console.log('finished preprocessors, doing training');
+
+			wrapper.find('svg #block_training_alg').simulate('click');
+			expect(wrapper.find({ name: 'training_alg', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted');
+			wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_training/1'}});
+			expect(updateFunc.callCount).to.equal(4);
+			expect(wrapper.props().data.contents).to.have.deep.property('blocks', {
+				'pre_testing': {
+					'algorithm': 'test/iris_preprocessor/1',
+					'inputs': {
+						'measurements': 'measurements'
+					},
+					'outputs': {
+						'measurements': 'measurements'
+					},
+					'parameters': {}
+				},
+				'pre_training': {
+					'algorithm': 'test/iris_preprocessor/1',
+					'inputs': {
+						'measurements': 'measurements'
+					},
+					'outputs': {
+						'measurements': 'measurements'
+					},
+					'parameters': {}
+				},
+				'testing_alg': {
+					'algorithm': '',
+					'inputs': {
+						'lda_machine': '',
+						'measurements': ''
+					},
+					'outputs': {
+						'scores': ''
+					},
+					'parameters': {}
+				},
+				'training_alg': {
+					'algorithm': 'test/iris_training/1',
+					'inputs': {
+						'measurements': 'measurements',
+						'species': 'species'
+					},
+					'outputs': {
+						'lda_machine': 'lda_machine'
+					},
+					'parameters': {}
+				}
+			});
+
+			//console.log('finished training, doing testing');
+
+			wrapper.find('svg #block_testing_alg').simulate('click');
+			expect(wrapper.find({ name: 'testing_alg', set: 'blocks'}).find('.tcBlockBackground').prop('className')).to.include('highlighted');
+			wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_testing/1'}});
+			expect(updateFunc.callCount).to.equal(5);
+			expect(wrapper.props().data.contents).to.have.deep.property('blocks', {
+				'pre_testing': {
+					'algorithm': 'test/iris_preprocessor/1',
+					'inputs': {
+						'measurements': 'measurements'
+					},
+					'outputs': {
+						'measurements': 'measurements'
+					},
+					'parameters': {}
+				},
+				'pre_training': {
+					'algorithm': 'test/iris_preprocessor/1',
+					'inputs': {
+						'measurements': 'measurements'
+					},
+					'outputs': {
+						'measurements': 'measurements'
+					},
+					'parameters': {}
+				},
+				'testing_alg': {
+					'algorithm': 'test/iris_testing/1',
+					'inputs': {
+						'lda_machine': 'lda_machine',
+						'measurements': 'measurements'
+					},
+					'outputs': {
+						'scores': 'scores'
+					},
+					'parameters': {}
+				},
+				'training_alg': {
+					'algorithm': 'test/iris_training/1',
+					'inputs': {
+						'measurements': 'measurements',
+						'species': 'species'
+					},
+					'outputs': {
+						'lda_machine': 'lda_machine'
+					},
+					'parameters': {}
+				}
+			});
+
+			//console.log('finished blocks, doing analyzer');
+
+			wrapper.find('svg #block_analyzer').simulate('click');
+			expect(wrapper.find({ name: 'analyzer', set: 'analyzers'}).find('.tcBlockBackground').prop('className')).to.include('highlighted');
+			wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'test/iris_analyzer/1'}});
+			expect(updateFunc.callCount).to.equal(6);
+			expect(wrapper.props().data.contents).to.have.deep.property('analyzers', {
+				'analyzer': {
+					'algorithm': 'test/iris_analyzer/1',
+					'inputs': {
+						'scores': 'scores',
+						'species': 'species'
+					},
+					'parameters': {}
+				}
+			});
+
+			//console.log('finished analyzer, doing cache check');
+
+			expect(wrapper.props().data).to.be.deep.equal({
+				'name': 'test/test/iris_advanced/1/iris',
+				'contents': {
+					'description': '',
+					'analyzers': {
+						'analyzer': {
+							'algorithm': 'test/iris_analyzer/1',
+							'inputs': {
+								'scores': 'scores',
+								'species': 'species'
+							},
+							'parameters': {}
+						}
+					},
+					'blocks': {
+						'pre_testing': {
+							'algorithm': 'test/iris_preprocessor/1',
+							'inputs': {
+								'measurements': 'measurements'
+							},
+							'outputs': {
+								'measurements': 'measurements'
+							},
+							'parameters': {}
+						},
+						'pre_training': {
+							'algorithm': 'test/iris_preprocessor/1',
+							'inputs': {
+								'measurements': 'measurements'
+							},
+							'outputs': {
+								'measurements': 'measurements'
+							},
+							'parameters': {}
+						},
+						'testing_alg': {
+							'algorithm': 'test/iris_testing/1',
+							'inputs': {
+								'lda_machine': 'lda_machine',
+								'measurements': 'measurements'
+							},
+							'outputs': {
+								'scores': 'scores'
+							},
+							'parameters': {}
+						},
+						'training_alg': {
+							'algorithm': 'test/iris_training/1',
+							'inputs': {
+								'measurements': 'measurements',
+								'species': 'species'
+							},
+							'outputs': {
+								'lda_machine': 'lda_machine'
+							},
+							'parameters': {}
+						}
+					},
+					'datasets': {
+						'testing_data': {
+							'database': 'iris/1',
+							'protocol': 'Main',
+							'set': 'training'
+						},
+						'training_data': {
+							'database': 'iris/1',
+							'protocol': 'Main',
+							'set': 'testing'
+						}
+					},
+					'globals': {
+						'queue': 'Default',
+						'environment': {
+							'name': 'Scientific Python 2.7',
+							'version': '0.0.4'
+						}
+					}
+				}
+			});
+		});
 	});
 });
diff --git a/conda/js/test/test_algs.json b/conda/js/test/test_algs.json
index 9d0bcd708fad5da8f4c7529b1301b6f3e0c841cf..3a41206a4fbb3e3b4a6a0e15a5af6c9493f3e135 100644
--- a/conda/js/test/test_algs.json
+++ b/conda/js/test/test_algs.json
@@ -1,4 +1,619 @@
 [
+        {
+                "name": "test/iris_preprocessor/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "measurements": {
+                                                        "type": "system/array_1d_floats/1"
+                                                }
+                                        },
+                                        "name": "group",
+                                        "outputs": {
+                                                "measurements": {
+                                                        "type": "system/array_1d_floats/1"
+                                                }
+                                        }
+                                }
+                        ],
+                        "description": "Rounds each measurement in an Iris dataset sample to the nearest integer",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/iris_testing/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "measurements": {
+                                                        "type": "system/array_1d_floats/1"
+                                                }
+                                        },
+                                        "name": "group",
+                                        "outputs": {
+                                                "scores": {
+                                                        "type": "system/float/1"
+                                                }
+                                        }
+                                },
+                                {
+                                        "inputs": {
+                                                "lda_machine": {
+                                                        "type": "tutorial/linear_machine/1"
+                                                }
+                                        },
+                                        "name": "group0"
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/iris_training/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "measurements": {
+                                                        "type": "system/array_1d_floats/1"
+                                                },
+                                                "species": {
+                                                        "type": "system/text/1"
+                                                }
+                                        },
+                                        "name": "group",
+                                        "outputs": {
+                                                "lda_machine": {
+                                                        "type": "tutorial/linear_machine/1"
+                                                }
+                                        }
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/linear_machine_projection/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "image": {
+                                                        "type": "system/array_2d_uint8/1"
+                                                }
+                                        },
+                                        "name": "main",
+                                        "outputs": {
+                                                "projections": {
+                                                        "type": "system/array_2d_floats/1"
+                                                }
+                                        }
+                                },
+                                {
+                                        "inputs": {
+                                                "subspace": {
+                                                        "type": "tutorial/linear_machine/1"
+                                                }
+                                        }
+                                }
+                        ],
+                        "description": "This algorithm linearizes and accumulates images into a buffer",
+                        "language": "python",
+                        "splittable": true
+                }
+        },
+        {
+                "name": "test/linear_machines_scoring/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "comparison_ids": {
+                                                        "type": "system/array_1d_uint64/1"
+                                                },
+                                                "probe_client_id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "probe_id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "probe_projections": {
+                                                        "type": "system/array_2d_floats/1"
+                                                }
+                                        },
+                                        "name": "probes",
+                                        "outputs": {
+                                                "scores": {
+                                                        "type": "tutorial/probe_scores/1"
+                                                }
+                                        }
+                                },
+                                {
+                                        "inputs": {
+                                                "template_client_id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "template_id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "template_projections": {
+                                                        "type": "system/array_2d_floats/1"
+                                                }
+                                        },
+                                        "name": "templates"
+                                }
+                        ],
+                        "description": "This algorithm generates comparison scores",
+                        "language": "python",
+                        "splittable": true
+                }
+        },
+        {
+                "name": "test/means_testing/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "measurements": {
+                                                        "type": "system/array_1d_floats/1"
+                                                }
+                                        },
+                                        "name": "group",
+                                        "outputs": {
+                                                "scores": {
+                                                        "type": "system/float/1"
+                                                }
+                                        }
+                                },
+                                {
+                                        "inputs": {
+                                                "means": {
+                                                        "type": "system/array_1d_floats/1"
+                                                }
+                                        },
+                                        "name": "group0"
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/means_training/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "measurements": {
+                                                        "type": "system/array_1d_floats/1"
+                                                },
+                                                "species": {
+                                                        "type": "system/text/1"
+                                                }
+                                        },
+                                        "name": "group",
+                                        "outputs": {
+                                                "means": {
+                                                        "type": "system/array_1d_floats/1"
+                                                }
+                                        }
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/pca/1",
+                "contents": {
+                        "parameters": {
+                                "number-of-components": {
+                                        "default": 5,
+                                        "type": "uint32"
+                                }
+                        },
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "image": {
+                                                        "type": "system/array_2d_uint8/1"
+                                                }
+                                        },
+                                        "outputs": {
+                                                "subspace": {
+                                                        "type": "tutorial/linear_machine/1"
+                                                }
+                                        }
+                                }
+                        ],
+                        "description": "Principal Component Analysis (PCA)",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/pcatest/1",
+                "contents": {
+                        "parameters": {
+                                "number-of-components": {
+                                        "default": 5,
+                                        "type": "uint32"
+                                }
+                        },
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "image": {
+                                                        "type": "system/array_2d_uint8/1"
+                                                }
+                                        },
+                                        "outputs": {
+                                                "subspace": {
+                                                        "type": "tutorial/linear_machine/1"
+                                                }
+                                        }
+                                },
+                                {
+                                        "inputs": {},
+                                        "name": "group"
+                                }
+                        ],
+                        "description": "Principal Component Analysis (PCA)",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/testing/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {},
+                                        "name": "group",
+                                        "outputs": {}
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "tutorial/linear_machine_projection/4",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "image": {
+                                                        "type": "system/array_2d_uint8/1"
+                                                },
+                                                "id": {
+                                                        "type": "system/uint64/1"
+                                                }
+                                        },
+                                        "name": "main",
+                                        "outputs": {
+                                                "projections": {
+                                                        "type": "system/array_2d_floats/1"
+                                                }
+                                        }
+                                },
+                                {
+                                        "inputs": {
+                                                "subspace": {
+                                                        "type": "tutorial/linear_machine/1"
+                                                }
+                                        }
+                                }
+                        ],
+                        "description": "This algorithm linearizes and accumulates images into a buffer",
+                        "language": "python",
+                        "splittable": true
+                }
+        },
+        {
+                "name": "tutorial/linear_machines_scoring/4",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "probe_projections": {
+                                                        "type": "system/array_2d_floats/1"
+                                                },
+                                                "comparison_ids": {
+                                                        "type": "system/array_1d_uint64/1"
+                                                },
+                                                "probe_id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "probe_client_id": {
+                                                        "type": "system/uint64/1"
+                                                }
+                                        },
+                                        "name": "probes",
+                                        "outputs": {
+                                                "scores": {
+                                                        "type": "tutorial/probe_scores/1"
+                                                }
+                                        }
+                                },
+                                {
+                                        "inputs": {
+                                                "template_client_id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "template_id": {
+                                                        "type": "system/uint64/1"
+                                                },
+                                                "template_projections": {
+                                                        "type": "system/array_2d_floats/1"
+                                                }
+                                        },
+                                        "name": "templates"
+                                }
+                        ],
+                        "description": "This algorithm generates comparison scores",
+                        "language": "python",
+                        "splittable": true
+                }
+        },
+        {
+                "name": "tutorial/pca/2",
+                "contents": {
+                        "parameters": {
+                                "number-of-components": {
+                                        "default": 5,
+                                        "type": "uint32"
+                                }
+                        },
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "image": {
+                                                        "type": "system/array_2d_uint8/1"
+                                                }
+                                        },
+                                        "outputs": {
+                                                "subspace": {
+                                                        "type": "tutorial/linear_machine/1"
+                                                }
+                                        }
+                                }
+                        ],
+                        "description": "Principal Component Analysis (PCA)",
+                        "language": "python",
+                        "splittable": false
+                }
+        },
+        {
+                "name": "test/iris_analyzer/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "scores": {
+                                                        "type": "system/float/1"
+                                                },
+                                                "species": {
+                                                        "type": "system/text/1"
+                                                }
+                                        },
+                                        "name": "group"
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "results": {
+                                "eer": {
+                                        "display": false,
+                                        "type": "float32"
+                                },
+                                "roc": {
+                                        "display": false,
+                                        "type": "plot/isoroc/1"
+                                },
+                                "scores_distribution": {
+                                        "display": false,
+                                        "type": "plot/bar/1"
+                                }
+                        }
+                }
+        },
+        {
+                "name": "test/iris_analyzer_error/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "scores": {
+                                                        "type": "system/float/1"
+                                                },
+                                                "species": {
+                                                        "type": "system/text/1"
+                                                }
+                                        },
+                                        "name": "group"
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "results": {
+                                "eer": {
+                                        "display": false,
+                                        "type": "float32"
+                                },
+                                "roc": {
+                                        "display": false,
+                                        "type": "plot/isoroc/1"
+                                },
+                                "scores_distribution": {
+                                        "display": false,
+                                        "type": "plot/bar/1"
+                                }
+                        }
+                }
+        },
+        {
+                "name": "test/iris_analyzertest/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "scores": {
+                                                        "type": "system/float/1"
+                                                },
+                                                "species": {
+                                                        "type": "system/text/1"
+                                                }
+                                        },
+                                        "name": "group"
+                                }
+                        ],
+                        "description": "",
+                        "language": "python",
+                        "results": {
+                                "eer": {
+                                        "display": false,
+                                        "type": "float32"
+                                },
+                                "roc": {
+                                        "display": false,
+                                        "type": "plot/isoroc/1"
+                                },
+                                "scores_distribution": {
+                                        "display": false,
+                                        "type": "plot/bar/1"
+                                }
+                        }
+                }
+        },
+        {
+                "name": "test/postperf_iso/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "scores": {
+                                                        "type": "tutorial/probe_scores/1"
+                                                }
+                                        },
+                                        "name": "main"
+                                }
+                        ],
+                        "description": "Standard metrics for biometric system evaluation",
+                        "language": "python",
+                        "results": {
+                                "eer": {
+                                        "display": true,
+                                        "type": "float32"
+                                },
+                                "number_of_negatives": {
+                                        "display": false,
+                                        "type": "int32"
+                                },
+                                "number_of_positives": {
+                                        "display": false,
+                                        "type": "int32"
+                                }
+                        }
+                }
+        },
+        {
+                "name": "tutorial/postperf_iso/1",
+                "contents": {
+                        "parameters": {},
+                        "uses": {},
+                        "groups": [
+                                {
+                                        "inputs": {
+                                                "scores": {
+                                                        "type": "tutorial/probe_scores/1"
+                                                }
+                                        },
+                                        "name": "main"
+                                }
+                        ],
+                        "description": "Standard metrics for biometric system evaluation",
+                        "language": "python",
+                        "results": {
+                                "number_of_negatives": {
+                                        "type": "int32",
+                                        "display": false
+                                },
+                                "far": {
+                                        "type": "float32",
+                                        "display": true
+                                },
+                                "roc": {
+                                        "type": "plot/isoroc/1",
+                                        "display": false
+                                },
+                                "scores_distribution": {
+                                        "type": "plot/bar/1",
+                                        "display": false
+                                },
+                                "eer": {
+                                        "type": "float32",
+                                        "display": true
+                                },
+                                "frr": {
+                                        "type": "float32",
+                                        "display": true
+                                },
+                                "threshold": {
+                                        "type": "float32",
+                                        "display": false
+                                },
+                                "number_of_positives": {
+                                        "type": "int32",
+                                        "display": false
+                                }
+                        }
+                }
+        },
         {
                 "name": "aythamimm/manhattan_scaled_scoring/63",
                 "contents": {
diff --git a/conda/js/test/test_dbs.json b/conda/js/test/test_dbs.json
index f9f6e2249181cb7167d09314d9fdfd893acb8c12..eb5d1a78d81fa681116aa0dd44e2ded8f6a8c25d 100644
--- a/conda/js/test/test_dbs.json
+++ b/conda/js/test/test_dbs.json
@@ -1,4 +1,39 @@
 [
+        {
+                "name": "iris/1",
+                "contents": {
+                        "description": "",
+                        "root_folder": "/not/needed",
+                        "protocols": [
+                                {
+                                        "name": "Main",
+                                        "sets": [
+                                                {
+                                                        "parameters": {},
+                                                        "name": "training",
+                                                        "outputs": {
+                                                                "measurements": "system/array_1d_floats/1",
+                                                                "species": "system/text/1"
+                                                        },
+                                                        "template": "iris",
+                                                        "view": "Training"
+                                                },
+                                                {
+                                                        "parameters": {},
+                                                        "name": "testing",
+                                                        "outputs": {
+                                                                "measurements": "system/array_1d_floats/1",
+                                                                "species": "system/text/1"
+                                                        },
+                                                        "template": "iris",
+                                                        "view": "Testing"
+                                                }
+                                        ],
+                                        "template": "iris"
+                                }
+                        ]
+                }
+        },
         {
                 "name": "atnt/3",
                 "contents": {
diff --git a/conda/js/test/test_exps.json b/conda/js/test/test_exps.json
index aedfb7feeb8344368f9fd9e6e6645e1f95a6e0c0..3a9cf6fa96cc3e76ad13091788d1b0442d9156e4 100644
--- a/conda/js/test/test_exps.json
+++ b/conda/js/test/test_exps.json
@@ -1,4 +1,83 @@
 [
+        {
+                "name": "test/test/iris_advanced/1/iris",
+                "contents": {
+                        "description": "",
+                        "analyzers": {
+                                "analyzer": {
+                                        "algorithm": "test/iris_analyzer/1",
+                                        "inputs": {
+                                                "scores": "scores",
+                                                "species": "species"
+                                        },
+                                        "parameters": {}
+                                }
+                        },
+                        "blocks": {
+                                "pre_testing": {
+                                        "algorithm": "test/iris_preprocessor/1",
+                                        "inputs": {
+                                                "measurements": "measurements"
+                                        },
+                                        "outputs": {
+                                                "measurements": "measurements"
+                                        },
+                                        "parameters": {}
+                                },
+                                "pre_training": {
+                                        "algorithm": "test/iris_preprocessor/1",
+                                        "inputs": {
+                                                "measurements": "measurements"
+                                        },
+                                        "outputs": {
+                                                "measurements": "measurements"
+                                        },
+                                        "parameters": {}
+                                },
+                                "testing_alg": {
+                                        "algorithm": "test/iris_testing/1",
+                                        "inputs": {
+                                                "lda_machine": "lda_machine",
+                                                "measurements": "measurements"
+                                        },
+                                        "outputs": {
+                                                "scores": "scores"
+                                        },
+                                        "parameters": {}
+                                },
+                                "training_alg": {
+                                        "algorithm": "test/iris_training/1",
+                                        "inputs": {
+                                                "measurements": "measurements",
+                                                "species": "species"
+                                        },
+                                        "outputs": {
+                                                "lda_machine": "lda_machine"
+                                        },
+                                        "parameters": {}
+                                }
+                        },
+                        "datasets": {
+                                "testing_data": {
+                                        "database": "iris/1",
+                                        "protocol": "Main",
+                                        "set": "training"
+                                },
+                                "training_data": {
+                                        "database": "iris/1",
+                                        "protocol": "Main",
+                                        "set": "testing"
+                                }
+                        },
+                        "globals": {
+                                "queue": "Default",
+                                "environment": {
+                                        "name": "Scientific Python 2.7",
+                                        "version": "0.0.4"
+                                }
+                        }
+                }
+        },
         {
                 "name": "tutorial/tutorial/eigenface/1/atnt-eigenfaces-7-comps",
                 "contents": {
diff --git a/conda/js/test/test_tcs.json b/conda/js/test/test_tcs.json
index 063aa9c0b556dc1a1aee0b984705bfd6d850b039..4ccebb7c004a23035c569c97fa17822ba5ea45f6 100644
--- a/conda/js/test/test_tcs.json
+++ b/conda/js/test/test_tcs.json
@@ -1,4 +1,182 @@
 [
+        {
+                "name": "test/iris_advanced/1",
+                "contents": {
+                        "analyzers": [
+                                {
+                                        "inputs": [
+                                                "scores",
+                                                "species"
+                                        ],
+                                        "name": "analyzer",
+                                        "synchronized_channel": "testing_data"
+                                }
+                        ],
+                        "blocks": [
+                                {
+                                        "inputs": [
+                                                "measurements",
+                                                "species"
+                                        ],
+                                        "name": "training_alg",
+                                        "outputs": [
+                                                "lda_machine"
+                                        ],
+                                        "synchronized_channel": "training_data"
+                                },
+                                {
+                                        "inputs": [
+                                                "lda_machine",
+                                                "measurements"
+                                        ],
+                                        "name": "testing_alg",
+                                        "outputs": [
+                                                "scores"
+                                        ],
+                                        "synchronized_channel": "testing_data"
+                                },
+                                {
+                                        "inputs": [
+                                                "measurements"
+                                        ],
+                                        "name": "pre_training",
+                                        "outputs": [
+                                                "measurements"
+                                        ],
+                                        "synchronized_channel": "training_data"
+                                },
+                                {
+                                        "inputs": [
+                                                "measurements"
+                                        ],
+                                        "name": "pre_testing",
+                                        "outputs": [
+                                                "measurements"
+                                        ],
+                                        "synchronized_channel": "testing_data"
+                                }
+                        ],
+                        "connections": [
+                                {
+                                        "channel": "testing_data",
+                                        "from": "testing_alg.scores",
+                                        "to": "analyzer.scores"
+                                },
+                                {
+                                        "channel": "training_data",
+                                        "from": "training_alg.lda_machine",
+                                        "to": "testing_alg.lda_machine"
+                                },
+                                {
+                                        "channel": "testing_data",
+                                        "from": "testing_data.species",
+                                        "to": "analyzer.species"
+                                },
+                                {
+                                        "channel": "training_data",
+                                        "from": "training_data.species",
+                                        "to": "training_alg.species"
+                                },
+                                {
+                                        "channel": "training_data",
+                                        "from": "training_data.measurements",
+                                        "to": "pre_training.measurements"
+                                },
+                                {
+                                        "channel": "training_data",
+                                        "from": "pre_training.measurements",
+                                        "to": "training_alg.measurements"
+                                },
+                                {
+                                        "channel": "testing_data",
+                                        "from": "testing_data.measurements",
+                                        "to": "pre_testing.measurements"
+                                },
+                                {
+                                        "channel": "testing_data",
+                                        "from": "pre_testing.measurements",
+                                        "to": "testing_alg.measurements"
+                                }
+                        ],
+                        "datasets": [
+                                {
+                                        "name": "training_data",
+                                        "outputs": [
+                                                "measurements",
+                                                "species"
+                                        ]
+                                },
+                                {
+                                        "name": "testing_data",
+                                        "outputs": [
+                                                "measurements",
+                                                "species"
+                                        ]
+                                }
+                        ],
+                        "description": "",
+                        "representation": {
+                                "blocks": {
+                                        "analyzer": {
+                                                "col": 59,
+                                                "height": 3,
+                                                "row": 6,
+                                                "width": 10
+                                        },
+                                        "pre_testing": {
+                                                "col": 19,
+                                                "height": 3,
+                                                "row": 5,
+                                                "width": 10
+                                        },
+                                        "pre_training": {
+                                                "col": 19,
+                                                "height": 3,
+                                                "row": 0,
+                                                "width": 10
+                                        },
+                                        "testing_alg": {
+                                                "col": 46,
+                                                "height": 3,
+                                                "row": 5,
+                                                "width": 10
+                                        },
+                                        "testing_data": {
+                                                "col": 6,
+                                                "height": 3,
+                                                "row": 6,
+                                                "width": 10
+                                        },
+                                        "training_alg": {
+                                                "col": 32,
+                                                "height": 3,
+                                                "row": 1,
+                                                "width": 10
+                                        },
+                                        "training_data": {
+                                                "col": 6,
+                                                "height": 3,
+                                                "row": 1,
+                                                "width": 10
+                                        }
+                                },
+                                "channel_colors": {
+                                        "testing_data": "#ff00ff",
+                                        "training_data": "#00ff00"
+                                },
+                                "connections": {
+                                        "pre_testing.measurements/testing_alg.measurements": [],
+                                        "pre_training.measurements/training_alg.measurements": [],
+                                        "testing_alg.scores/analyzer.scores": [],
+                                        "testing_data.measurements/pre_testing.measurements": [],
+                                        "testing_data.species/analyzer.species": [],
+                                        "training_alg.lda_machine/testing_alg.lda_machine": [],
+                                        "training_data.measurements/pre_training.measurements": [],
+                                        "training_data.species/training_alg.species": []
+                                }
+                        }
+                }
+        },
         {
                 "name": "tutorial/eigenface/1",
                 "contents": {