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_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_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_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_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_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 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_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_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_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()
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_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()