def test_remove_cell_from_nrn(self): with NEURON(), CommNode("Control-NEURON", coverage=True) as ncn, \ Blender(), CommNode("Control-Blender", coverage=True) as bcn: # Load TestCell.hoc - create a group ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc1 = h.TestCell();') # Load cell into first group and show it bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();" "bpy.ops.blenderneuron.import_groups();") # Create 2nd cell ncn.client.run_command('tc2 = h.TestCell();') # Delete the first cell from NRN ncn.client.run_command('tc1 = None;' 'del tc1;') # Add second group, check the number of ui cells ui_cell_count = bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "bpy.ops.blenderneuron.import_groups();" "return_value = len(bpy.context.scene.BlenderNEURON.groups[0].root_entries);" ) self.assertEqual(ui_cell_count, 1) # Get the name of the visible cell of the second group ui_cell_name = bcn.client.run_command( "return_value = bpy.context.scene.BlenderNEURON.groups[1].root_entries[0].name;" ) self.assertEqual(ui_cell_name, "TestCell[1].soma")
def test_ugly_render_curves(self): with NEURON(), CommNode("Control-NEURON", coverage=True) as ncn, \ Blender(), CommNode("Control-Blender", coverage=True) as bcn: # Load TestCell.hoc ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc = h.TestCell();') bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # Non-smooth curves bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].interaction_granularity = 'Cell';" "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].smooth_sections = False;" "bpy.ops.blenderneuron.import_groups();") # Non-smooth curves bevel = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].interaction_granularity = 'Cell';" "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].as_lines = True;" "bpy.ops.blenderneuron.import_groups();" "return_value = bpy.data.curves['Group.000_bezier.001'].bevel_depth" ) # Should have no bevel self.assertEqual(bevel, 0)
def test_copy_group(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Load TestCell.hoc - create a group ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc1 = h.TestCell();') # Load cell into first group bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # Create 2nd cell ncn.client.run_command('tc2 = h.TestCell();') # Add second group, and shift 2nd cell up by 5 um bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "bpy.ops.blenderneuron.import_groups();" "bpy.data.objects['TestCell[1].soma'].location[2] += 5;") # Test group copying logic group_int_granularity = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].interaction_granularity = 'Section';" "bpy.context.scene.BlenderNEURON.groups_index = 1;" "group = bpy.data.scenes['Scene'].BlenderNEURON.groups[1];" "group.copy_from_group = 'Group.000';" "bpy.ops.blenderneuron.copy_from_group();" "return_value = group.interaction_granularity;") self.assertEqual(group_int_granularity, 'Section') bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_glare(self): with NEURON(), CommNode("Control-NEURON", coverage=True) as ncn, \ Blender(), CommNode("Control-Blender", coverage=True) as bcn: bcn.client.run_command('bpy.ops.blenderneuron.add_neon_effect();') # Adding 2nd time should not fail either bcn.client.run_command('bpy.ops.blenderneuron.add_neon_effect();')
def test_import_remove_import_again(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Load TestCell.hoc - create a group ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc = h.TestCell();') bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # Import the cell and check if created in correct location x, y, z = bcn.client.run_command( "bpy.ops.blenderneuron.import_groups();" "return_value = list(bpy.data.objects['TestCell[0].soma'].location)" ) self.assertAlmostEqual(x, 150, 1) self.assertAlmostEqual(y, -176, 1) self.assertAlmostEqual(z, 0, 1) # Shift the cell up by 100 um bcn.client.run_command( "bpy.data.objects['TestCell[0].soma'].location = [150, -176, 100];" ) # Re-Import the cell and check if overwrote the shift above x, y, z = bcn.client.run_command( "bpy.ops.blenderneuron.import_groups();" "return_value = list(bpy.data.objects['TestCell[0].soma'].location)" ) self.assertAlmostEqual(z, 0, 1) # Shift the cell up again by 100 um bcn.client.run_command( "bpy.data.objects['TestCell[0].soma'].location = [150, -176, 100];" ) # Remove the group, there should be no cell objects count = bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_remove();" "return_value = len([ob for ob in bpy.data.objects if 'TestCell[0].soma' in ob.name])" ) # Add a new group, import it x, y, z = bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "bpy.ops.blenderneuron.import_groups();" "return_value = list(bpy.data.objects['TestCell[0].soma'].location)" ) # The z position should be the original position (not shifted) self.assertAlmostEqual(z, 0, 1) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_save_groups(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Load TestCell.hoc - create a group ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc1 = h.TestCell();') # Load cell into first group bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # Create 2nd cell ncn.client.run_command('tc2 = h.TestCell();') # Add second group, and shift 2nd cell up by 5 um bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "bpy.ops.blenderneuron.import_groups();" "bpy.data.objects['TestCell[1].soma'].location[2] += 5;") file1 = 'test_group1.json' file2 = 'test_group2.json' try: # Test group saving bcn.client.run_command( "groups = bpy.types.Object.BlenderNEURON_node.groups;" "groups['Group.000'].to_file('" + file1 + "');" "groups['Group.001'].to_file('" + file2 + "');") # Read the saved files import json with open(file1) as f1, open(file2) as f2: json1 = json.load(f1) json2 = json.load(f2) # check that correct cells were saved self.assertEqual(json1['roots'][0]['name'], 'TestCell[0].soma') self.assertEqual(json2['roots'][0]['name'], 'TestCell[1].soma') # Check that the z-location was saved correctly self.assertEqual(json1['roots'][0]['coords'][-1], 0) # 2nd cell should be shifted up by 5um self.assertEqual(json2['roots'][0]['coords'][-1], 5) finally: os.remove(file1) os.remove(file2) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_blender_coverage(self): with NEURON(), Blender(), \ CommNode('Control-NEURON') as cn, \ CommNode("Control-Blender") as cb: self.assertEqual(cn.client.ping(), 1) self.assertEqual(cb.client.ping(), 1) cn.client.end_code_coverage() cb.client.end_code_coverage()
def test_simulator_settings_exchange(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # set settings in Blender and send to NEURON bcn.client.run_command( "params = bpy.data.scenes['Scene'].BlenderNEURON.simulator_settings;" "params.neuron_tstop = 1111;" "params.time_step = 0.002;" "params.abs_tolerance = 0.005;" "params.temperature = 44;" "params.integration_method = '1';" "bpy.ops.blenderneuron.sim_settings_to_neuron();" "bpy.ops.blenderneuron.sim_settings_from_neuron();" ) self.assertEqual(1111, bcn.client.run_command( "params = bpy.data.scenes['Scene'].BlenderNEURON.simulator_settings;" "return_value = params.neuron_tstop" )) self.assertAlmostEqual(0.005, bcn.client.run_command( "params = bpy.data.scenes['Scene'].BlenderNEURON.simulator_settings;" "return_value = params.abs_tolerance" ), places=3) self.assertEqual(44, bcn.client.run_command( "params = bpy.data.scenes['Scene'].BlenderNEURON.simulator_settings;" "return_value = params.temperature" )) self.assertEqual('1', bcn.client.run_command( "params = bpy.data.scenes['Scene'].BlenderNEURON.simulator_settings;" "return_value = params.integration_method" )) # Test fixed step integration bcn.client.run_command( "params = bpy.data.scenes['Scene'].BlenderNEURON.simulator_settings;" "params.time_step = 0.002;" "params.integration_method = '0';" "bpy.ops.blenderneuron.sim_settings_to_neuron();" "bpy.ops.blenderneuron.sim_settings_from_neuron();" ) self.assertAlmostEqual(0.002, bcn.client.run_command( "params = bpy.data.scenes['Scene'].BlenderNEURON.simulator_settings;" "return_value = params.time_step" ), places=3) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_can_connect_to_neuron(self): # Start Blender with a running node with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # See if Blender is able to connect to the NEURON process node result = bcn.client.run_command("return_value = str(bpy.types.Object.BlenderNEURON_node.client)") self.assertIn("Proxy", result) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test(): from neuron import h h.load_file('stdrun.hoc') cm1 = CommNode("NEURON") soma = h.Section() soma.insert('pas') soma.insert('hh') h.tstop = 100 cm2 = CommNode("Blender") tstart = h.t cm2.client.run_command("h.run()") self.assertGreater(h.t, tstart)
def test_stop_server(self): with CommNode("NEURON") as cm: cm.stop_server() self.assertTrue(cm.server_thread is None) self.assertTrue(cm.server is None) self.assertTrue(cm.server_address is None)
def test_file_cleanup(self): with CommNode("NEURON") as cm: server_address_file = cm.get_end_address_file(cm.server_end) # Should exist before exit self.assertTrue(os.path.exists(server_address_file)) # Should be gone after exit self.assertFalse(os.path.exists(server_address_file))
def test_mpi(self): with NEURON(), CommNode("Control-NEURON", coverage=True) as ncn, \ Blender(), CommNode("Control-Blender", coverage=True) as bcn: # Load TestCell.hoc - create a cell name:mpi rank map ncn.client.run_command( 'h.load_file("tests/TestCell.hoc");' 'tc = h.TestCell();' 'from blenderneuron.neuronstart import BlenderNEURON as bn_node;' ) # Get section name before MPI map is provided self.assertEqual( ncn.client.run_command( 'return_value = bn_node.rank_section_name(tc.soma.name());' ), 'TestCell[0].soma') # Provide MPI map ncn.client.run_command( 'pc = h.ParallelContext();' 'single_rank_name = "TestCell[0]";' 'mpi_rank_name = "TestCell[0]";' 'mpimap = {};' 'mpimap[single_rank_name] = { "name": mpi_rank_name, "rank": pc.id() };' 'mpimap["TestCell[1]"] = { "name": mpi_rank_name, "rank": 2 };' 'bn_node.init_mpi(pc, mpimap);') # Get section name after MPI init self.assertEqual( ncn.client.run_command( 'return_value = bn_node.rank_section_name(tc.soma.name());' ), 'TestCell[0].soma') # Cell without a specific section self.assertEqual( ncn.client.run_command( 'return_value = bn_node.rank_section_name("TestCell[0]");' ), 'TestCell[0]') # Try section that does not exist on the rank self.assertEqual( ncn.client.run_command( 'return_value = bn_node.rank_section_name("TestCell[1].soma");' ), None)
def test_error_handling(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: from xmlrpc.client import Fault try: bcn.client.run_command('1/0') except Fault: pass try: ncn.client.run_command('1/0') except Fault: pass bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_double_stop_server(self): with CommNode("NEURON") as cm: # Should stop on end of "with" pass self.assertTrue(cm.server_thread is None) self.assertTrue(cm.server is None) self.assertTrue(cm.server_address is None) # This should not blow up cm.stop_server()
def test_group_select_all_none_invert(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Create a few named root sections in NEURON ncn.client.run_command('s1 = h.Section(name="soma1");' 's2 = h.Section(name="soma2");') # Refresh the default cell group in Blender bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();" ) # Check the group contains the two root sections self.assertEqual(2, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = len(group.root_entries);" )) # Unselect all, Check that no cells are selected self.assertEqual(True, bcn.client.run_command( "bpy.ops.blenderneuron.unselect_all_cells();" "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = all(cell.selected == False for cell in group.root_entries)" )) # Select all, Check that all cells are selected self.assertEqual(True, bcn.client.run_command( "bpy.ops.blenderneuron.select_all_cells();" "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = all(cell.selected for cell in group.root_entries)" )) # Unselect last cell, invert selection, and check that first cell is unselected self.assertEqual(False, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "group.root_entries[-1].selected = False;" "bpy.ops.blenderneuron.invert_cell_selection();" "return_value = group.root_entries[0].selected" )) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def __enter__(self): self.process.start() waited = 0 while waited < 10: with CommNode("Control-Blender") as bcn: if bcn.client is not None and bcn.client.ping() == 1: break else: sleep(0.5) return self
def test_remove_cells_groups(self): with NEURON(), CommNode("Control-NEURON", coverage=True) as ncn, \ Blender(), CommNode("Control-Blender", coverage=True) as bcn: # Load TestCell.hoc - create a group ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc1 = h.TestCell();') # Load cell into first group bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # Create 2nd cell ncn.client.run_command('tc2 = h.TestCell();') # Add second group, and shift 2nd cell up by 5 um group_count = bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "bpy.ops.blenderneuron.import_groups();" "bpy.data.objects['TestCell[1].soma'].location[2] += 5;" "return_value = len(bpy.context.scene.BlenderNEURON.groups);") self.assertEqual(group_count, 2) # Unselect 2nd cell from 2nd group and remove the empty group group_count = bcn.client.run_command( "bpy.context.scene.BlenderNEURON.groups[1].root_entries[1].selected = False;" "bpy.ops.blenderneuron.cell_group_remove();" "return_value = len(bpy.context.scene.BlenderNEURON.groups);") self.assertEqual(group_count, 1) # Remove the last group group_count = bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_remove();" "return_value = len(bpy.context.scene.BlenderNEURON.groups);") self.assertEqual(group_count, 0)
def test_simulator_run(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Create a root section in NEURON ncn.client.run_command('s1 = h.Section(name="soma1");' 's1.insert("pas");' 's1.insert("hh");') # Run the sim bcn.client.run_command( "bpy.ops.blenderneuron.init_and_run_neuron()" ) # Check that sim time is advanced self.assertAlmostEqual(5.0, ncn.client.run_command('return_value=h.t'), places=1) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_queueing_commands(self): with CommNode("Blender") as cm1: with CommNode("NEURON") as cm2: task1 = cm1.client.enqueue_command('a = 1') task2 = cm1.client.enqueue_command('b = 0') task3 = cm1.client.enqueue_command('c = a / b') task4 = cm1.client.enqueue_command('d = "never happened"') i = 0 while i < 1 and cm1.client.get_task_status(task4) == 'QUEUED': sleep(0.1) i += 0.1 self.assertEqual(cm1.client.get_task_status(task1), 'SUCCESS') self.assertEqual(cm1.client.get_task_status(task2), 'SUCCESS') self.assertEqual(cm1.client.get_task_status(task3), 'ERROR') self.assertEqual(cm1.client.get_task_status(task4), 'ERROR') # Should fail on non-existing task self.assertEqual(cm1.client.get_task_status(9999), "DOES_NOT_EXIST")
def test_mpi_synset(self): with NEURON(), CommNode("Control-NEURON", coverage=True) as ncn, \ Blender(), CommNode("Control-Blender", coverage=True) as bcn: # Load TestCell.hoc - create a cell name:mpi rank map ncn.client.run_command( 'h.load_file("tests/TestCell.hoc");' 'tc = h.TestCell();' 'from blenderneuron.neuronstart import BlenderNEURON as bn_node;' 'bn_node.update_section_index();') # Provide MPI map - first cell on this rank, 2nd cell on another rank ncn.client.run_command( 'pc = h.ParallelContext();' 'mpimap = {};' 'mpimap["TestCell[0]"] = { "name": "TestCell[0]", "rank": 0 };' 'mpimap["TestCell[1]"] = { "name": "TestCell[1]", "rank": 1 };' 'bn_node.init_mpi(pc, mpimap);') ncn.client.run_command('from json import load;' 'f = open("tests/test_synset.json");' 'bn_node.create_synapses(load(f));' 'f.close();')
def test_Blender_first(self): with CommNode("Blender") as cm1: with CommNode("NEURON") as cm2: self.assertEqual(cm1.client.ping(), 1) self.assertEqual(cm2.client.ping(), 1)
def test_import_export_cell(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Load TestCell.hoc - create a group ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc = h.TestCell();') bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # Check that the cell was loaded self.assertEqual( "TestCell[0].soma", bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = group.root_entries[0].name")) # Import the cell and check if created in correct location x, y, z = bcn.client.run_command( "bpy.ops.blenderneuron.import_groups();" "return_value = list(bpy.data.objects['TestCell[0].soma'].location)" ) self.assertAlmostEqual(x, 150, 1) self.assertAlmostEqual(y, -176, 1) self.assertAlmostEqual(z, 0, 1) # And cell bounding box dimensions are correct dim_x, dim_y, dim_z = bcn.client.run_command( "return_value = list(bpy.data.objects['TestCell[0].soma'].dimensions)" ) self.assertAlmostEqual(dim_x, 165.45, 1) self.assertAlmostEqual(dim_y, 165.80, 1) self.assertAlmostEqual(dim_z, 1, 0) # Shift the cell up by 100 um, and export to NRN bcn.client.run_command( "bpy.data.objects['TestCell[0].soma'].location = [150, -176, 100];" "bpy.ops.blenderneuron.update_groups_with_view_data();" "bpy.ops.blenderneuron.export_groups();") # Test if coordinates in NRN changed by same amount z_soma, z_dend1, z_dend2 = ncn.client.run_command( 'return_value = [h.z3d(0,sec=tc.soma), h.z3d(0,sec=tc.dendrites[-1]), h.z3d(0,sec=tc.dendrites[15])]' ) self.assertEqual(z_soma, 100.0) self.assertEqual(z_soma, z_dend1) self.assertEqual(z_dend1, z_dend2) # Re-import the cell and check if change persists x, y, z = bcn.client.run_command( "bpy.ops.blenderneuron.import_groups();" "return_value = list(bpy.data.objects['TestCell[0].soma'].location)" ) self.assertAlmostEqual(z, 100, 1) # And that duplicate objects were not created count = bcn.client.run_command( "cellObjs = [ob for ob in bpy.data.objects if 'TestCell[0].soma' in ob.name];" "return_value = len(cellObjs)") self.assertEqual(count, 1) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_object_levels(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Load TestCell.hoc - and add somatic stimulus ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc = h.TestCell();' 'ic = h.IClamp(0.5);' 'ic.amp = 1; ic.delay = 1; ic.dur = 10;') bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # ----------------- Cell level objects --------------- # soma_object_exists, dendrite_object_exists = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].interaction_granularity = 'Cell';" "bpy.ops.blenderneuron.import_groups();" "objs = bpy.data.objects;" "return_value = ('TestCell[0].soma' in objs, 'TestCell[0].dendrites[0]' in objs);" ) self.assertTrue(soma_object_exists) self.assertFalse(dendrite_object_exists) # Import animation - animate WHOLE CELL soma_mat_exists, dendrite_mat_exists, = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].record_activity = True;" "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].recording_granularity = 'Cell';" "bpy.ops.blenderneuron.import_groups();" "mats = bpy.data.materials;" "return_value = ('TestCell[0].soma' in mats, 'TestCell[0].dendrites[0]' in mats);" ) self.assertTrue(soma_mat_exists) self.assertFalse(dendrite_mat_exists) soma_emission_start, soma_emission_end, = bcn.client.run_command( "mats = bpy.data.materials;" "bpy.context.scene.frame_set(0);" "start_emit = mats['TestCell[0].soma'].emit;" "bpy.context.scene.frame_set(5);" "end_emit = mats['TestCell[0].soma'].emit;" "return_value = (start_emit, end_emit);") self.assertGreater(soma_emission_start, 0) self.assertGreater(soma_emission_end, soma_emission_start) # Import animation - animate EACH SECTION soma_mat_exists, dendrite_mat_exists, = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].record_activity = True;" "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].recording_granularity = 'Section';" "bpy.ops.blenderneuron.import_groups();" "mats = bpy.data.materials;" "return_value = ('TestCell[0].soma' in mats, 'TestCell[0].dendrites[0]' in mats);" ) self.assertTrue(soma_mat_exists) self.assertTrue(dendrite_mat_exists) dend_emission_start, dend_emission_end, = bcn.client.run_command( "mats = bpy.data.materials;" "bpy.context.scene.frame_set(0);" "start_emit = mats['TestCell[0].dendrites[0]'].emit;" "bpy.context.scene.frame_set(5);" "end_emit = mats['TestCell[0].dendrites[0]'].emit;" "return_value = (start_emit, end_emit);") self.assertGreater(dend_emission_start, 0) self.assertGreater(dend_emission_end, dend_emission_start) # --------------- Section level objects ------------------- # soma_object_exists, dendrite_object_exists = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].interaction_granularity = 'Section';" "bpy.ops.blenderneuron.import_groups();" "objs = bpy.data.objects;" "return_value = ('TestCell[0].soma' in objs, 'TestCell[0].dendrites[0]' in objs);" ) self.assertTrue(soma_object_exists) self.assertTrue(dendrite_object_exists) # Import animation - animate WHOLE CELL soma_mat_exists, dendrite_mat_exists, = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].record_activity = True;" "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].recording_granularity = 'Cell';" "bpy.ops.blenderneuron.import_groups();" "mats = bpy.data.materials;" "return_value = ('TestCell[0].soma' in mats, 'TestCell[0].dendrites[0]' in mats);" ) self.assertTrue(soma_mat_exists) self.assertFalse(dendrite_mat_exists) soma_emission_start, soma_emission_end, = bcn.client.run_command( "mats = bpy.data.materials;" "bpy.context.scene.frame_set(0);" "start_emit = mats['TestCell[0].soma'].emit;" "bpy.context.scene.frame_set(5);" "end_emit = mats['TestCell[0].soma'].emit;" "return_value = (start_emit, end_emit);") self.assertGreater(soma_emission_start, 0) self.assertGreater(soma_emission_end, soma_emission_start) # Import animation - animate EACH SECTION soma_mat_exists, dendrite_mat_exists, = bcn.client.run_command( "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].record_activity = True;" "bpy.data.scenes['Scene'].BlenderNEURON.groups[0].recording_granularity = 'Section';" "bpy.ops.blenderneuron.import_groups();" "mats = bpy.data.materials;" "return_value = ('TestCell[0].soma' in mats, 'TestCell[0].dendrites[0]' in mats);" ) self.assertTrue(soma_mat_exists) self.assertTrue(dendrite_mat_exists) dend_emission_start, dend_emission_end, = bcn.client.run_command( "mats = bpy.data.materials;" "bpy.context.scene.frame_set(0);" "start_emit = mats['TestCell[0].dendrites[0]'].emit;" "bpy.context.scene.frame_set(5);" "end_emit = mats['TestCell[0].dendrites[0]'].emit;" "return_value = (start_emit, end_emit);") self.assertGreater(dend_emission_start, 0) self.assertGreater(dend_emission_end, dend_emission_start) # Test group renaming logic group_name = bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups[0];" "group.name = 'TEST_GROUP';" "return_value = group.name;") self.assertEqual(group_name, 'TEST_GROUP') bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_no_client(self): with CommNode("NEURON") as cm: self.assertTrue(cm.client is None) self.assertTrue(cm.client_address is None)
def test_wrong_end(self): try: with CommNode("FOO") as cm: raise Exception("FOO should not be a valid end type") except: pass
def test_find_synapses(self): with NEURON(), CommNode("Control-NEURON", coverage=True) as ncn, \ Blender(), CommNode("Control-Blender", coverage=True) as bcn: # Load TestCell.hoc - create a group ncn.client.run_command('h.load_file("tests/TestCell.hoc");' 'tc1 = h.TestCell();') # Load cell into first group bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();") # Create 2nd cell ncn.client.run_command('tc2 = h.TestCell();') # Add second group, and shift 2nd cell up by 5 um bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "bpy.ops.blenderneuron.import_groups();" "bpy.data.objects['TestCell[1].soma'].location[2] += 5;") # Setup synapse former to look for synapses between the two cells syn_count = bcn.client.run_command( "syn_set = bpy.data.scenes['Scene'].BlenderNEURON.synapse_sets[0];" "syn_set.section_pattern_source = '*dend*';" "syn_set.group_dest = 'Group.001';" "syn_set.is_reciprocal = True;" "syn_set.create_spines = True;" "syn_set.use_radius = False;" "syn_set.max_syns_per_pt = 1;" "bpy.ops.blenderneuron.find_synapse_locations();" "return_value = len(bpy.data.objects['SynapsePreview'].data.splines)" ) self.assertEqual(syn_count, 32) # There should be no synapses when max search distance is very small syn_count = bcn.client.run_command( "syn_set = bpy.data.scenes['Scene'].BlenderNEURON.synapse_sets[0];" "syn_set.max_distance = 1;" "bpy.ops.blenderneuron.find_synapse_locations();" "return_value = len(bpy.data.objects['SynapsePreview'].data.splines)" ) self.assertEqual(syn_count, 0) # When using radius, it should find the same synapses at a shortened distance syn_count = bcn.client.run_command( "syn_set = bpy.data.scenes['Scene'].BlenderNEURON.synapse_sets[0];" "syn_set.use_radius = True;" "syn_set.max_distance = 4;" "bpy.ops.blenderneuron.find_synapse_locations();" "return_value = len(bpy.data.objects['SynapsePreview'].data.splines)" ) self.assertEqual(syn_count, 32) # Sub-divide the cell sections in NEURON ncn.client.run_command( "[setattr(sec,'nseg', 10) for sec in h.allsec()];") # And create the found synapses bcn.client.run_command("bpy.ops.blenderneuron.create_synapses();") # check if the syns were created correctly in NEURON syn1_sec, syn1_x = ncn.client.run_command( 'seg = h.ExpSyn[0].get_segment();' 'return_value = (seg.sec.name(), seg.x);') self.assertEqual(syn1_sec, 'TestCell[1].dendrites[4]') self.assertEqual(syn1_x, 0.95) # middle of the 10th segment = 0.95 syn2_sec, syn2_x = ncn.client.run_command( 'seg = h.ExpSyn[1].get_segment();' 'return_value = (seg.sec.name(), seg.x);') self.assertEqual(syn2_sec, 'SynapseSet_001_Spine[0].head') self.assertEqual(syn2_x, 0.5) # middle of the spine head # Save the found synapses into a JSON file syn_file = 'syn_test.json' bcn.client.run_command( "bpy.context.scene.BlenderNEURON.synapse_set.save_synapses('" + syn_file + "');") import json with open(syn_file) as f: syns = json.load(f) import os try: os.remove(syn_file) except: pass self.assertEqual(syns['entries'][0]['dest_section'], 'TestCell[1].dendrites[4]') self.assertEqual(syns['entries'][0]['source_section'], 'TestCell[0].dendrites[4]') self.assertEqual(syns['entries'][0]['dest_x'], 1.0) self.assertEqual(syns['entries'][0]['source_x'], 1.0) # Test renaming logic syn_set_name = bcn.client.run_command( "syn_set = bpy.data.scenes['Scene'].BlenderNEURON.synapse_sets[0];" "syn_set.name = 'TEST_NAME';" "return_value = syn_set.name;") self.assertEqual(syn_set_name, 'TEST_NAME')
def test_quitting_from_client(self): with CommNode("Blender") as cm1: with CommNode("NEURON") as cm2: cm1.client.run_command('quit()')
def test_add_remove_group_and_cells(self): with NEURON(), CommNode("Control-NEURON") as ncn, \ Blender(), CommNode("Control-Blender") as bcn: # Create a few named root sections in NEURON ncn.client.run_command('s1 = h.Section(name="soma1");' 's2 = h.Section(name="soma2");') # Check that a default group was added self.assertEqual([1, 0], bcn.client.run_command( "groups = bpy.data.scenes['Scene'].BlenderNEURON.groups;" "count = len(groups);" "index = bpy.data.scenes['Scene'].BlenderNEURON.groups_index;" "return_value = [count, index];" )) # Refresh the list after adding the cells - this should not break the later tests # Check that there are 2 cells within the group self.assertEqual(2, bcn.client.run_command( "bpy.ops.blenderneuron.get_cell_list_from_neuron();" "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = len(group.root_entries);" )) # The last cell listed is the last cell created self.assertEqual("soma2", bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = group.root_entries[-1].name" )) # Check that both cells are selected self.assertEqual(True, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = all(cell.selected for cell in group.root_entries)" )) # Create a second cell group # Check that a group was added self.assertEqual(2, bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "return_value = len(bpy.data.scenes['Scene'].BlenderNEURON.groups)" )) # Check that there are 2 cells within the 2nd group self.assertEqual(2, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups[1];" "return_value = len(group.root_entries)" )) # Check that NONE of the cells are selected in 2nd group self.assertEqual(True, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups[1];" "return_value = all(cell.selected == False for cell in group.root_entries)" )) # Select the last cell of the *2nd* group # Check that the last cell of the *1st* group becomes unselected self.assertEqual(False, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups[1];" "group.root_entries[-1].selected = True;" "group = bpy.data.scenes['Scene'].BlenderNEURON.groups['Group.000'];" "return_value = group.root_entries[-1].selected" )) # Now select the first cell of the 2nd group (both cells should be selected) # Delete the second cell group (this should free the 2nd group's cells) # Check that a group was removed self.assertEqual(1, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups[1];" "group.root_entries[0].selected = True;" "bpy.ops.blenderneuron.cell_group_remove();" "return_value = len(bpy.data.scenes['Scene'].BlenderNEURON.groups)" )) # Add a new cell group (it should now contain the free'd cells) # Check that a group was added self.assertEqual(2, bcn.client.run_command( "bpy.ops.blenderneuron.cell_group_add();" "return_value = len(bpy.data.scenes['Scene'].BlenderNEURON.groups)" )) # Check that both cells are selected self.assertEqual(True, bcn.client.run_command( "group = bpy.data.scenes['Scene'].BlenderNEURON.groups[1];" "return_value = all(cell.selected for cell in group.root_entries)" )) bcn.client.end_code_coverage() ncn.client.end_code_coverage()
def test_server_established(self): # Start Blender with a running node with Blender(), CommNode("Control-Blender") as bcn: self.assertEqual(bcn.client.ping(), 1) bcn.client.end_code_coverage()