void ShortAxisFitting::setThetaDelta(ShortAxisOptimizationInput* input, const alglib::real_1d_array& x) { Cmiss_field_module_id field_module = (input->field_module); std::vector<Cmiss_node_id>& cmiss_nodes(*(input->cmiss_nodes)); Cmiss_field_id coordinate = (input->coordinates_rc); Cmiss_field_cache_id cache = (input->cache); double* initialSegmentLengths = input->initialSegmentLengths; int* saxNodes = input->saxNodes; int numberOfModelFrames = input->numberOfModelFrames; int NUMBER_OF_SEGMENTS = input->NUMBER_OF_SEGMENTS; int NUMBER_OF_SAX_NODES = input->NUMBER_OF_SAX_NODES; double** result = input->result; //This is expected to be preallocated for heap efficiency int* endoNodeIds = input->endoNodesIds; const int NUMBER_OF_ENDO_NODES = 48; //Ignore the apex int ctr = 0; double coord[3]; int frame = input->frame; Point3D centroids[4]; centroids[0] = input->centroids[0]; centroids[1] = input->centroids[1]; centroids[2] = input->centroids[2]; centroids[3] = input->centroids[3]; //First 12 endo nodes saxcentroid 0, next 12 1... //Set the theta variation in x to the mesh { Cmiss_field_module_begin_change(field_module); { double time = ((double) frame) / ((double) numberOfModelFrames); if (frame == (numberOfModelFrames - 1)) { time = 1.0; } Cmiss_field_cache_set_time(cache, time); for (int nc = 0; nc < NUMBER_OF_ENDO_NODES; nc++) { ctr = nc/12; double deltaTheta = ((int)(x[ctr]*100000))/100000.0; Cmiss_field_cache_set_node(cache, cmiss_nodes[endoNodeIds[nc] - 1]); Cmiss_field_evaluate_real(coordinate, cache, 3, coord); Point3D start(coord); start = start + centroids[nc/12]; double nTheta = atan2(start.z, start.x) + deltaTheta; double dist = sqrt(start.x * start.x + start.z * start.z); coord[0] = dist * cos(nTheta) - centroids[nc/12].x; coord[2] = dist * sin(nTheta) - centroids[nc/12].z; Cmiss_field_assign_real(coordinate, cache, 3, coord); } } Cmiss_field_module_end_change(field_module); } }
void ShortAxisFitting::getSegmentLengths(ShortAxisOptimizationInput* input) { int ctr = 0; double* lengthArray = *(input->result); double* initialSegmentLengths = input->initialSegmentLengths; double coord[3]; Cmiss_field_id coordinates_rc = input->coordinates_rc; Cmiss_field_cache_id cache = input->cache; std::vector<Cmiss_node_id>& cmiss_nodes(*input->cmiss_nodes); double** segmentNodes = input->segmentNodes; int frame = input->frame; //for (int frame = 0; frame < input->numberOfModelFrames; frame++) { double time = ((double) frame) / ((double) input->numberOfModelFrames); if (frame == (input->numberOfModelFrames - 1)) { time = 1.0; } Cmiss_field_cache_set_time(cache, time); for (int seg = 0; seg < input->NUMBER_OF_SEGMENTS; seg++) { Cmiss_field_cache_set_node(cache, cmiss_nodes[segmentNodes[seg][0]]); Cmiss_field_evaluate_real(coordinates_rc, cache, 3, coord); Point3D start(coord); Cmiss_field_cache_set_node(cache, cmiss_nodes[segmentNodes[seg][1]]); Cmiss_field_evaluate_real(coordinates_rc, cache, 3, coord); Point3D end(coord); lengthArray[ctr++] = start.distance(end); } } ctr = 0; double error = 0; if (initialSegmentLengths != NULL) { //for (int frame = 0; frame < input->numberOfModelFrames; frame++) { for (int seg = 0; seg < input->NUMBER_OF_SEGMENTS; seg++) { error += fabs(initialSegmentLengths[ctr] - lengthArray[ctr]); ctr++; } } } input->segmentMatchError = error; }
static void Element_tool_interactive_event_handler(void *device_id, struct Interactive_event *event,void *element_tool_void, struct Graphics_buffer *graphics_buffer) /******************************************************************************* LAST MODIFIED 18 November 2005 DESCRIPTION : Input handler for input from devices. <device_id> is a unique address enabling the editor to handle input from more than one device at a time. The <event> describes the type of event, button numbers and key modifiers, and the volume of space affected by the interaction. Main events are button press, movement and release. ==============================================================================*/ { enum Interactive_event_type event_type; FE_value time, xi[MAXIMUM_ELEMENT_XI_DIMENSIONS]; int clear_selection, element_dimension, i, input_modifier, number_of_xi_points, shift_pressed; int number_in_xi[MAXIMUM_ELEMENT_XI_DIMENSIONS]; struct FE_element *picked_element; struct FE_element_shape *element_shape; struct Element_tool *element_tool; struct Interaction_volume *interaction_volume,*temp_interaction_volume; struct LIST(Scene_picked_object) *scene_picked_object_list; struct Scene *scene; struct Cmiss_rendition *rendition = NULL; FE_value_triple *xi_points; ENTER(Element_tool_interactive_event_handler); if (device_id&&event&&(element_tool= (struct Element_tool *)element_tool_void)) { Cmiss_region_begin_hierarchical_change(element_tool->region); interaction_volume=Interactive_event_get_interaction_volume(event); scene=Interactive_event_get_scene(event); if (scene != 0) { event_type=Interactive_event_get_type(event); input_modifier=Interactive_event_get_input_modifier(event); shift_pressed=(INTERACTIVE_EVENT_MODIFIER_SHIFT & input_modifier); switch (event_type) { case INTERACTIVE_EVENT_BUTTON_PRESS: { /* interaction only works with first mouse button */ if (1==Interactive_event_get_button_number(event)) { scene_picked_object_list= Scene_pick_objects(scene,interaction_volume,graphics_buffer); if (scene_picked_object_list != 0) { element_tool->picked_element_was_unselected=1; if (0 != (picked_element=Scene_picked_object_list_get_nearest_element( scene_picked_object_list,(struct Cmiss_region *)NULL, element_tool->select_elements_enabled, element_tool->select_faces_enabled, element_tool->select_lines_enabled, (struct Scene_picked_object **)NULL, &rendition, (struct Cmiss_graphic **)NULL))) { /* Open command_field of picked_element in browser */ if (element_tool->command_field) { if (element_tool->time_keeper) { time = Time_keeper_get_time(element_tool->time_keeper); } else { time = 0; } /* since we don't really have fields constant over an element, evaluate at its centre */ element_dimension = get_FE_element_dimension(picked_element); for (i = 0; i < element_dimension; i++) { number_in_xi[i] = 1; } get_FE_element_shape(picked_element, &element_shape); if (FE_element_shape_get_xi_points_cell_centres( element_shape, number_in_xi, &number_of_xi_points, &xi_points)) { /*???debug*/printf("element_tool: xi ="); for (i = 0; i < element_dimension; i++) { xi[i] = xi_points[0][i]; /*???debug*/printf(" %g",xi[i]); } /*???debug*/printf("\n"); Cmiss_field_module_id field_module = Cmiss_field_get_field_module(element_tool->command_field); Cmiss_field_cache_id field_cache = Cmiss_field_module_create_cache(field_module); Cmiss_field_cache_set_time(field_cache, time); Cmiss_field_cache_set_mesh_location(field_cache, picked_element, element_dimension, xi); char *command_string = Cmiss_field_evaluate_string(element_tool->command_field, field_cache); if (command_string) { Execute_command_execute_string(element_tool->execute_command, command_string); DEALLOCATE(command_string); } Cmiss_field_cache_destroy(&field_cache); Cmiss_field_module_destroy(&field_module); DEALLOCATE(xi_points); } } Cmiss_field_group_id group = Cmiss_rendition_get_selection_group(rendition); if (group) { Cmiss_region_id temp_region = Cmiss_rendition_get_region(rendition); Cmiss_field_module_id field_module = Cmiss_region_get_field_module(temp_region); int dimension = Cmiss_element_get_dimension(picked_element); Cmiss_mesh_id master_mesh = Cmiss_field_module_find_mesh_by_dimension(field_module, dimension); Cmiss_field_element_group_id element_group = Cmiss_field_group_get_element_group(group, master_mesh); Cmiss_mesh_destroy(&master_mesh); if (element_group) { Cmiss_mesh_group_id mesh_group = Cmiss_field_element_group_get_mesh(element_group); element_tool->picked_element_was_unselected = !Cmiss_mesh_contains_element(Cmiss_mesh_group_base_cast(mesh_group), picked_element); Cmiss_mesh_group_destroy(&mesh_group); Cmiss_field_element_group_destroy(&element_group); } Cmiss_field_group_destroy(&group); Cmiss_field_module_destroy(&field_module); } } REACCESS(FE_element)(&(element_tool->last_picked_element), picked_element); /*(if ((clear_selection = !shift_pressed) &&((!picked_element)|| (element_tool->picked_element_was_unselected)))*/ clear_selection = !shift_pressed; if (clear_selection) { if (element_tool->region) { Cmiss_rendition *root_rendition = Cmiss_region_get_rendition_internal(element_tool->region); Cmiss_field_group_id root_group = Cmiss_rendition_get_selection_group(root_rendition); if (root_group) { Cmiss_field_group_clear_region_tree_element(root_group); Cmiss_field_group_destroy(&root_group); } Cmiss_rendition_destroy(&root_rendition); } } if (picked_element) { REACCESS(Cmiss_rendition)(&(element_tool->rendition), rendition); Cmiss_region *sub_region = NULL; Cmiss_field_group_id sub_group = NULL; Cmiss_mesh_group_id mesh_group = 0; if (element_tool->rendition) { sub_region = Cmiss_rendition_get_region(element_tool->rendition); sub_group = Cmiss_rendition_get_or_create_selection_group(element_tool->rendition); if (sub_group) { int dimension = Cmiss_element_get_dimension(picked_element); Cmiss_field_module_id field_module = Cmiss_region_get_field_module(sub_region); Cmiss_mesh_id temp_mesh = Cmiss_field_module_find_mesh_by_dimension(field_module, dimension); Cmiss_field_element_group_id element_group = Cmiss_field_group_get_element_group(sub_group, temp_mesh); if (!element_group) element_group = Cmiss_field_group_create_element_group(sub_group, temp_mesh); mesh_group = Cmiss_field_element_group_get_mesh(element_group); Cmiss_field_element_group_destroy(&element_group); Cmiss_mesh_destroy(&temp_mesh); Cmiss_field_module_destroy(&field_module); } } if (mesh_group) { Cmiss_mesh_group_add_element(mesh_group, picked_element); Cmiss_mesh_group_destroy(&mesh_group); } if (sub_group) { Cmiss_field_group_destroy(&sub_group); } } DESTROY(LIST(Scene_picked_object))(&(scene_picked_object_list)); } element_tool->motion_detected=0; REACCESS(Interaction_volume)( &(element_tool->last_interaction_volume),interaction_volume); } } break; case INTERACTIVE_EVENT_MOTION_NOTIFY: case INTERACTIVE_EVENT_BUTTON_RELEASE: { if (element_tool->last_interaction_volume&& ((INTERACTIVE_EVENT_MOTION_NOTIFY==event_type) || (1==Interactive_event_get_button_number(event)))) { if (INTERACTIVE_EVENT_MOTION_NOTIFY==event_type) { element_tool->motion_detected=1; } if (element_tool->last_picked_element) { /* unselect last_picked_element if not just added */ if ((INTERACTIVE_EVENT_BUTTON_RELEASE==event_type)&& shift_pressed&&(!(element_tool->picked_element_was_unselected))) { struct LIST(FE_element) *temp_element_list = CREATE(LIST(FE_element))(); ADD_OBJECT_TO_LIST(FE_element)(element_tool->last_picked_element, temp_element_list); Cmiss_rendition_remove_selection_from_element_list_of_dimension(element_tool->rendition, temp_element_list, Cmiss_element_get_dimension(element_tool->last_picked_element)); DESTROY(LIST(FE_element))(&temp_element_list); } } else if (element_tool->motion_detected) { /* rubber band select */ temp_interaction_volume= create_Interaction_volume_bounding_box( element_tool->last_interaction_volume,interaction_volume); if (temp_interaction_volume != 0) { if (INTERACTIVE_EVENT_MOTION_NOTIFY==event_type) { if (!element_tool->rubber_band) { /* create rubber_band object and put in scene */ element_tool->rubber_band=CREATE(GT_object)( "element_tool_rubber_band",g_POLYLINE, element_tool->rubber_band_material); ACCESS(GT_object)(element_tool->rubber_band); } Interaction_volume_make_polyline_extents( temp_interaction_volume,element_tool->rubber_band); } else { #if defined (USE_SCENE_OBJECT) Scene_remove_graphics_object(scene,element_tool->rubber_band); #endif DEACCESS(GT_object)(&(element_tool->rubber_band)); } if (INTERACTIVE_EVENT_BUTTON_RELEASE==event_type) { scene_picked_object_list= Scene_pick_objects(scene,temp_interaction_volume, graphics_buffer); if (scene_picked_object_list != 0) { Region_element_map *element_map = (Region_element_map *)Scene_picked_object_list_get_picked_region_sorted_elements( scene_picked_object_list, element_tool->select_elements_enabled, element_tool->select_faces_enabled, element_tool->select_lines_enabled); if (element_map) { Cmiss_region *sub_region = NULL; Cmiss_field_group_id sub_group = NULL; Cmiss_rendition *region_rendition = NULL; Cmiss_mesh_group_id mesh_group[MAXIMUM_ELEMENT_XI_DIMENSIONS]; int iter = 0; for (iter = 0; iter < MAXIMUM_ELEMENT_XI_DIMENSIONS; iter++) { mesh_group[iter] = 0; } Region_element_map::iterator pos; for (pos = element_map->begin(); pos != element_map->end(); ++pos) { if (pos->first != sub_region) { if (sub_group) { Cmiss_field_group_destroy(&sub_group); } for (iter = 0; iter < MAXIMUM_ELEMENT_XI_DIMENSIONS; iter++) { if (mesh_group[iter]) { Cmiss_mesh_group_destroy(&(mesh_group[iter])); } } if (region_rendition) { Cmiss_rendition_destroy(®ion_rendition); } sub_region = pos->first; if (sub_region) { region_rendition= Cmiss_region_get_rendition_internal(sub_region); sub_group = Cmiss_rendition_get_or_create_selection_group(region_rendition); } } if (sub_region && sub_group) { Cmiss_field_module_id field_module = Cmiss_region_get_field_module(sub_region); int dimension = Cmiss_element_get_dimension(pos->second); if (dimension <= MAXIMUM_ELEMENT_XI_DIMENSIONS) { if (!mesh_group[dimension - 1]) { Cmiss_mesh_id temp_mesh = Cmiss_field_module_find_mesh_by_dimension(field_module, dimension); Cmiss_field_element_group_id element_group = Cmiss_field_group_get_element_group(sub_group, temp_mesh); if (!element_group) { element_group = Cmiss_field_group_create_element_group(sub_group, temp_mesh); } mesh_group[dimension - 1] = Cmiss_field_element_group_get_mesh(element_group); Cmiss_field_element_group_destroy(&element_group); Cmiss_mesh_destroy(&temp_mesh); } Cmiss_mesh_group_add_element(mesh_group[dimension - 1], pos->second); } Cmiss_field_module_destroy(&field_module); } } if (sub_group) { Cmiss_field_group_destroy(&sub_group); } for (iter = 0; iter < MAXIMUM_ELEMENT_XI_DIMENSIONS; iter++) { if (mesh_group[iter]) { Cmiss_mesh_group_destroy(&(mesh_group[iter])); } } if (region_rendition) { Cmiss_rendition_destroy(®ion_rendition); } delete element_map; } DESTROY(LIST(Scene_picked_object))( &(scene_picked_object_list)); } } DESTROY(Interaction_volume)(&temp_interaction_volume); } } if (INTERACTIVE_EVENT_BUTTON_RELEASE==event_type) { Element_tool_reset((void *)element_tool); } } } break; default: { display_message(ERROR_MESSAGE, "Element_tool_interactive_event_handler. Unknown event type"); } break; }
void StrainMeasures::embedStrainOnElements(std::string fieldname, std::vector<std::string>& strain) { const unsigned int num_strains = numberOfModelFrames_; double times[1024]; for (unsigned int j = 0; j < num_strains; j++) { times[j] = static_cast<double>(j) / (num_strains - 1.0); } Cmiss_time_sequence_id time_sequence = Cmiss_field_module_get_matching_time_sequence(field_module, num_strains, times); Cmiss_field_module_begin_change(field_module); //Create Node template Cmiss_nodeset_id nodeset = Cmiss_field_module_find_nodeset_by_name(field_module, "cmiss_nodes"); Cmiss_node_template_id nodeTemplate = Cmiss_nodeset_create_node_template(nodeset); //Create the field Cmiss_field_id strainField = Cmiss_field_module_create_field(field_module, fieldname.c_str(), "finite number_of_components 1 component_names value"); if (!strainField) { std::cout << "Unable to create field " << fieldname << std::endl; return; } Cmiss_node_template_define_field(nodeTemplate, strainField); Cmiss_node_template_define_time_sequence(nodeTemplate, strainField, time_sequence); //Create Element template Cmiss_mesh_id mesh = Cmiss_field_module_find_mesh_by_dimension(field_module, 3); Cmiss_element_template_id element_template = Cmiss_mesh_create_element_template(mesh); Cmiss_element_template_set_shape_type(element_template, CMISS_ELEMENT_SHAPE_CUBE); Cmiss_element_template_set_number_of_nodes(element_template, 1); Cmiss_element_basis_id constant_basis = Cmiss_field_module_create_element_basis(field_module, 3, CMISS_BASIS_FUNCTION_CONSTANT); const int local_node_index = 1; Cmiss_element_template_define_field_simple_nodal(element_template, strainField, -1, constant_basis, 1, &local_node_index); Cmiss_element_basis_destroy(&constant_basis); //Map strains to elements std::map<int, int> elemStrainMap; //Cmiss element no is mapped to strain array number //APLAX elemStrainMap[3] = elemStrainMap[10] = 1; //Array id base 0 elemStrainMap[15] = elemStrainMap[22] = 18; //Average of strain ids 2 and 8 elemStrainMap[27] = elemStrainMap[34] = 12; elemStrainMap[39] = elemStrainMap[46] = 17; elemStrainMap[40] = elemStrainMap[45] = 17; elemStrainMap[28] = elemStrainMap[33] = 10; elemStrainMap[16] = elemStrainMap[21] = 19; //Average of strain ids 11 and 5 elemStrainMap[4] = elemStrainMap[9] = 4; //TCH elemStrainMap[11] = elemStrainMap[12] = 2; //Array id base 0 elemStrainMap[23] = elemStrainMap[24] = 20; //Average of strain ids 3 and 9 elemStrainMap[35] = elemStrainMap[36] = 8; elemStrainMap[47] = elemStrainMap[48] = 16; elemStrainMap[41] = elemStrainMap[42] = 16; elemStrainMap[17] = elemStrainMap[18] = 11; elemStrainMap[29] = elemStrainMap[30] = 21; //Average of strain ids 12 and 6 elemStrainMap[5] = elemStrainMap[6] = 5; //FCH elemStrainMap[1] = elemStrainMap[2] = 3; //Array id base 0 elemStrainMap[13] = elemStrainMap[14] = 22; //Average of 10 and 4 elemStrainMap[25] = elemStrainMap[26] = 4; elemStrainMap[37] = elemStrainMap[38] = 23; //Average of strains 14 and 15 elemStrainMap[43] = elemStrainMap[44] = 24; //Average of strains 16 and 13 elemStrainMap[31] = elemStrainMap[32] = 6; elemStrainMap[19] = elemStrainMap[20] = 25; //Average of strains 7 and 1 elemStrainMap[7] = elemStrainMap[8] = 0; std::vector<std::string> allStrain = strain; //Add the additional strains 18 - 23 std::string s2 = strain[1]; std::string s8 = strain[7]; std::string s11 = strain[10]; std::string s5 = strain[5]; std::string s9 = strain[8]; std::string s3 = strain[2]; std::string s12 = strain[11]; std::string s6 = strain[6]; std::string s10 = strain[9]; std::string s4 = strain[3]; std::string s14 = strain[13]; std::string s15 = strain[14]; std::string s16 = strain[15]; std::string s13 = strain[12]; std::string s1 = strain[0]; std::string s7 = strain[6]; std::vector<std::string> compute; compute.push_back(s2); compute.push_back(s8); compute.push_back(s11); compute.push_back(s5); compute.push_back(s9); compute.push_back(s3); compute.push_back(s12); compute.push_back(s6); compute.push_back(s10); compute.push_back(s4); compute.push_back(s14); compute.push_back(s15); compute.push_back(s16); compute.push_back(s13); compute.push_back(s7); compute.push_back(s1); for (int cptc = 0; cptc < 16; cptc += 2) { std::vector<std::string> strain1; std::vector<std::string> strain2; std::ostringstream ss; boost::split(strain1, compute[cptc], boost::is_any_of(",")); boost::split(strain2, compute[cptc + 1], boost::is_any_of(",")); for (unsigned int j = 0; j < num_strains - 1; j++) { double value1 = atof(strain1[j].c_str()); double value2 = atof(strain2[j].c_str()); ss << (value1 + value2) * 0.5 << ","; } ss << "0.0"; allStrain.push_back(ss.str()); } for (unsigned int i = 0; i < num_elements; i++) { Cmiss_node_id temporaryNode = Cmiss_nodeset_create_node(nodeset, extraNodeStartID++, nodeTemplate); Cmiss_element_template_set_node(element_template, 1, temporaryNode); //Link node with the element Cmiss_element_merge(elements[i], element_template); Cmiss_field_cache_set_node(fieldCache, temporaryNode); std::vector<std::string> strains; boost::split(strains, allStrain[elemStrainMap[i + 1]], boost::is_any_of(",")); for (unsigned int j = 0; j < num_strains; j++) { double value = atof(strains[j].c_str()); double time = times[j]; Cmiss_field_cache_set_time(fieldCache, time); Cmiss_field_assign_real(strainField,fieldCache,1,&value); } Cmiss_node_destroy(&temporaryNode); } Cmiss_field_module_end_change(field_module); Cmiss_field_destroy(&strainField); Cmiss_element_template_destroy(&element_template); Cmiss_node_template_destroy(&nodeTemplate); Cmiss_nodeset_destroy(&nodeset); //Calling the following leads to the error ERROR: DESTROY(FE_time_sequence). Positive access_count //Cmiss_time_sequence_destroy(&time_sequence); }
std::vector<std::string> StrainMeasures::getSixteenSegmentTorsions(double wall_xi) { //The measure of change due to helix rotation between the walls //Setup segments const double base_start = 1.0; const double mid_start = 0.7; const double apex_start = 0.5; const double apex_end = 0.001; const double wall_epi = 1.0; if (wall_xi == 1.0) wall_xi = 0.99; std::vector<WallSegment> segments; //APLAX const double apexAngle = 0.0; //Base WallSegment seg1(3, 7); //Segment 2 seg1.setXIA(apexAngle, 0.5 * (base_start + mid_start), wall_xi); seg1.setXIB(apexAngle, 0.5 * (base_start + mid_start), wall_epi); WallSegment seg2(5, 1); //Segment 5 seg2.setXIA(apexAngle, 0.5 * (base_start + mid_start), wall_xi); seg2.setXIB(apexAngle, 0.5 * (base_start + mid_start), wall_epi); //Mid WallSegment seg3(7, 11); //Segment 8 seg3.setXIA(apexAngle, 0.5 * (mid_start + apex_start), wall_xi); seg3.setXIB(apexAngle, 0.5 * (mid_start + apex_start), wall_epi); WallSegment seg4(5, 9); //Segment 11 seg4.setXIA(apexAngle, 0.5 * (mid_start + apex_start), wall_xi); seg4.setXIB(apexAngle, 0.5 * (mid_start + apex_start), wall_epi); //Apex WallSegment seg5(12, 16); //Segment 13 seg5.setXIA(0.8, 0.5 * (apex_start + apex_end), wall_xi); seg5.setXIB(0.8, 0.5 * (apex_start + apex_end), wall_epi); WallSegment seg6(9, 13); //Segment 15 seg6.setXIA(0.1, 0.5 * (apex_start + apex_end), wall_xi); seg6.setXIB(0.1, 0.5 * (apex_start + apex_end), wall_epi); //TCH const double tchAngle = 2.5 / 3.0; //Base WallSegment tseg1(4, 8); //Segment 3 tseg1.setXIA(tchAngle, 0.5 * (base_start + mid_start), wall_xi); tseg1.setXIB(tchAngle, 0.5 * (base_start + mid_start), wall_epi); WallSegment tseg2(6, 2); //Segment 6 tseg2.setXIA(tchAngle, 0.5 * (base_start + mid_start), wall_xi); tseg2.setXIB(tchAngle, 0.5 * (base_start + mid_start), wall_epi); //Mid WallSegment tseg3(8, 12); //Segment 9 tseg3.setXIA(tchAngle, 0.5 * (mid_start + apex_start), wall_xi); tseg3.setXIB(tchAngle, 0.5 * (mid_start + apex_start), wall_epi); WallSegment tseg4(6, 10); //Segment 12 tseg4.setXIA(tchAngle, 0.5 * (mid_start + apex_start), wall_xi); tseg4.setXIB(tchAngle, 0.5 * (mid_start + apex_start), wall_epi); //Apex WallSegment tseg5(12, 16); //Segment 14 tseg5.setXIA(tchAngle, 0.5 * (apex_start + apex_end), wall_xi); tseg5.setXIB(tchAngle, 0.5 * (apex_start + apex_end), wall_epi); WallSegment tseg6(10, 14); //Segment 16 tseg6.setXIA(tchAngle, 0.5 * (apex_start + apex_end), wall_xi); tseg6.setXIB(tchAngle, 0.5 * (apex_start + apex_end), wall_epi); //FCH const double fchAngle = 1.0 / 3.0; //Base WallSegment fseg1(1, 5); //Segment 4 fseg1.setXIA(fchAngle, 0.5 * (base_start + mid_start), wall_xi); fseg1.setXIB(fchAngle, 0.5 * (base_start + mid_start), wall_epi); WallSegment fseg2(7, 3); //Segment 1 fseg2.setXIA(fchAngle, 0.5 * (base_start + mid_start), wall_xi); fseg2.setXIB(fchAngle, 0.5 * (base_start + mid_start), wall_epi); //Mid WallSegment fseg3(5, 9); //Segment 10 fseg3.setXIA(fchAngle, 0.5 * (mid_start + apex_start), wall_xi); fseg3.setXIB(fchAngle, 0.5 * (mid_start + apex_start), wall_epi); WallSegment fseg4(7, 11); //Segment 7 fseg4.setXIA(fchAngle, 0.5 * (mid_start + apex_start), wall_xi); fseg4.setXIB(fchAngle, 0.5 * (mid_start + apex_start), wall_epi); //Apex WallSegment fseg5(9, 13); //Segment 14+15 fseg5.setXIA(fchAngle, apex_start, wall_xi); fseg5.setXIB(fchAngle, apex_end, wall_epi); WallSegment fseg6(11, 15); //Segment 13+16 fseg6.setXIA(fchAngle, apex_start, wall_xi); fseg6.setXIB(fchAngle, apex_end, wall_epi); segments.clear(); segments.push_back(fseg2); //1 segments.push_back(seg1); //2 segments.push_back(tseg1); //3 segments.push_back(fseg1); //4 segments.push_back(seg2); //5 segments.push_back(tseg2); //6 segments.push_back(fseg4); //7 segments.push_back(seg3); //8 segments.push_back(tseg3); //9 segments.push_back(fseg3); //10 segments.push_back(seg4); //11 segments.push_back(tseg4); //12 segments.push_back(seg5); //13 segments.push_back(tseg5); //14 segments.push_back(seg6); //15 segments.push_back(tseg6); //16 //Setup the active strain segments int aplaxStrainIds[] = { 1, 7, 12, 14, 10, 4 }; int tchStrainIds[] = { 2, 8, 13, 15, 11, 5 }; int fchStrainIds[] = { 0, 6, 9, 3 }; int activeStrainSegments[16]; unsigned int totalActiveSegments = 0; memset(activeStrainSegments, 0, sizeof(int) * 16); for (int i = 0; i < 6; i++) activeStrainSegments[aplaxStrainIds[i]] = 1; totalActiveSegments += 6; for (int i = 0; i < 6; i++) activeStrainSegments[tchStrainIds[i]] = 1; totalActiveSegments += 6; for (int i = 0; i < 4; i++) activeStrainSegments[fchStrainIds[i]] = 1; totalActiveSegments += 4; //Compute the strain for each segment over time unsigned int samples = numberOfModelFrames_; double* length = new double[samples]; double* nstrain = new double[numberOfModelFrames_]; double* avgstrain = new double[numberOfModelFrames_]; double temp_array[3], temp_array1[3]; unsigned int numSegments = segments.size(); memset(avgstrain, 0, numberOfModelFrames_ * sizeof(double)); std::vector<std::string> strains; std::stringstream ss; //Setup the header for (unsigned int i = 0; i < numSegments; i++) { WallSegment& seg = segments[i]; for (unsigned int dt = 0; dt < samples; dt++) { double time = ((double) dt) / (samples - 1.0); Cmiss_field_cache_set_time(fieldCache, time); temp_array1[0] = temp_array1[1] = temp_array1[2] = 0.0; //Since cmiss id starts at 1 subtract 1 from seg.elementid? Cmiss_field_cache_set_mesh_location(fieldCache, elements[seg.elementida - 1], 3, seg.xia); Cmiss_field_evaluate_real(coordianteField, fieldCache, 3, temp_array); Cmiss_field_cache_set_mesh_location(fieldCache, elements[seg.elementida - 1], 3, seg.xib); Cmiss_field_evaluate_real(coordianteField, fieldCache, 3, temp_array1); length[dt] = fabs(temp_array1[2]); } ss << " 0.0"; avgstrain[0] = 0.0; for (unsigned int dt = 1; dt < samples - 1; dt++) { nstrain[dt] = length[dt] - length[0]; ss << "," << nstrain[dt]; avgstrain[dt] += nstrain[dt] * activeStrainSegments[i]; } ss << "," << nstrain[0]; avgstrain[numberOfModelFrames_ - 1] += nstrain[0] * activeStrainSegments[i]; strains.push_back(ss.str()); //Clear the buffer ss.str(""); } ss << avgstrain[0]; for (unsigned int dt = 1; dt < numberOfModelFrames_; dt++) { ss << "," << avgstrain[dt] / totalActiveSegments; } strains.push_back(ss.str()); delete[] length; delete[] nstrain; delete[] avgstrain; return strains; }
std::vector<std::string> StrainMeasures::getLinearDistortion(double* wall_xi, unsigned int cnt, double power) { unsigned int xdiscret = 25; unsigned int ydiscret = 25; //Create points of interest array double **pointsOfInterest_x = new double*[xdiscret + 1]; double **pointsOfInterest_y = new double*[xdiscret + 1]; for (unsigned int i = 0; i <= xdiscret; i++) { pointsOfInterest_x[i] = new double[ydiscret + 1]; pointsOfInterest_y[i] = new double[ydiscret + 1]; } double delx = 1.0 / xdiscret; double dely = 1.0 / ydiscret; for (unsigned int xd = 0; xd <= xdiscret; xd++) { double xinc = xd * delx; if (xinc == 0.0) xinc = 0.001; if (xinc == 1.0) xinc = 0.99; for (unsigned int yd = 0; yd <= ydiscret; yd++) { double yinc = yd * dely; if (yinc == 0.0) yinc = 0.001; if (yinc == 1.0) yinc = 0.99; pointsOfInterest_x[xd][yd] = xinc; pointsOfInterest_y[xd][yd] = yinc; } } Cmiss_field_id principleStarinsField = Cmiss_field_module_find_field_by_name(field_module, "principal_strains"); double temp_array[3]; double coordinates[3]; long nan_count = 0; std::vector<std::string> results; std::vector<LevelSet*>* coordSets = new std::vector<LevelSet*>(); std::vector<LevelSet*>* deformSets = new std::vector<LevelSet*>(); for (unsigned int ls = 0; ls < cnt; ls++) { coordSets->clear(); deformSets->clear(); for (unsigned int mt = 0; mt < numberOfModelFrames_; mt++) { double time = ((double) mt) / (numberOfModelFrames_ - 1.0); LevelSet* myCoordLevelSet = new LevelSet(num_elements, xdiscret + 1, ydiscret + 1); LevelSet* myDeformLevelSet = new LevelSet(num_elements, xdiscret + 1, ydiscret + 1, 1); Cmiss_field_cache_set_time(fieldCache, time); nan_count = 0; for (unsigned int xd = 0; xd <= xdiscret; xd++) { for (unsigned int yd = 0; yd <= ydiscret; yd++) { for (unsigned int elementId = 0; elementId < num_elements; elementId++) { coordinates[0] = pointsOfInterest_x[xd][yd]; coordinates[1] = pointsOfInterest_y[xd][yd]; coordinates[2] = wall_xi[ls]; //std::cout<<coordinates[0]<<" "<<coordinates[1]<<" "<<coordinates[2]<<std::endl; temp_array[0] = temp_array[1] = temp_array[2] = 0.0; Cmiss_field_cache_set_mesh_location(fieldCache, elements[elementId], 3, coordinates); Cmiss_field_evaluate_real(principleStarinsField, fieldCache, 3, temp_array); double result = getLocalDeformation(temp_array, &nan_count); myDeformLevelSet->setData(elementId, xd, yd, &result, 1); Cmiss_field_evaluate_real(coordianteField, fieldCache, 3, temp_array); myCoordLevelSet->setData(elementId, xd, yd, temp_array, 3); } } } coordSets->push_back(myCoordLevelSet); deformSets->push_back(myDeformLevelSet); } std::stringstream ss; unsigned int numpoints = coordSets->size(); for (unsigned int i = 0; i < numpoints; i++) { LevelSet* myCoordLevelSet = coordSets->at(i); LevelSet* myDeformLevelSet = deformSets->at(i); ss << myDeformLevelSet->getLPSum(0, power) / myCoordLevelSet->getArea(); if (i < (numpoints - 1)) ss << ","; delete myCoordLevelSet; delete myDeformLevelSet; } results.push_back(ss.str()); } //Clean up delete deformSets; delete coordSets; for (unsigned int i = 0; i <= xdiscret; i++) { delete[] pointsOfInterest_x[i]; delete[] pointsOfInterest_y[i]; } delete[] pointsOfInterest_x; delete[] pointsOfInterest_y; Cmiss_field_destroy(&principleStarinsField); return results; }
std::vector<std::string> StrainMeasures::getSegmentStrains(std::string fieldName) { std::vector<std::string> strains(19); Cmiss_field_id field = Cmiss_field_module_find_field_by_name(field_module, fieldName.c_str()); //Compute strains unsigned int numSegments = mySegments->size(); double temp_array1[3]; double temp_array2[3]; //#define printcoord #ifdef printcoord #include "MeshTopology.h" std::vector<Cmiss_node_id> myNodes(100); Cmiss_nodeset_id nodeset = Cmiss_field_module_find_nodeset_by_name(field_module, "cmiss_nodes"); Cmiss_node_iterator_id nodeIterator = Cmiss_nodeset_create_node_iterator(nodeset); Cmiss_node_id node = Cmiss_node_iterator_next(nodeIterator); if (node != 0) { double temp_array[3]; while (node) { int node_id = Cmiss_node_get_identifier(node); myNodes[node_id - 1] = node; node = Cmiss_node_iterator_next(nodeIterator); } } Cmiss_nodeset_destroy(&nodeset); Cmiss_node_iterator_destroy(&nodeIterator); std::vector<int> Nodes(27); Nodes[8] = aplaxNodes8; Nodes[7] = aplaxNodes7; Nodes[6] = aplaxNodes6; Nodes[5] = aplaxNodes5; Nodes[4] = aplaxNodes4; Nodes[3] = aplaxNodes3; Nodes[2] = aplaxNodes2; Nodes[1] = aplaxNodes1; Nodes[0] = aplaxNodes0; Nodes[9] = tchNodes0; Nodes[10] = tchNodes1; Nodes[11] = tchNodes2; Nodes[12] = tchNodes3; Nodes[13] = tchNodes4; Nodes[14] = tchNodes5; Nodes[15] = tchNodes6; Nodes[16] = tchNodes7; Nodes[17] = tchNodes8; Nodes[18] = fchNodes0; Nodes[19] = fchNodes1; Nodes[20] = fchNodes2; Nodes[21] = fchNodes3; Nodes[22] = fchNodes4; Nodes[23] = fchNodes5; Nodes[24] = fchNodes6; Nodes[25] = fchNodes7; Nodes[26] = fchNodes8; #endif std::vector<std::vector<double> > aplaxLengths; std::vector<std::vector<double> > tchLengths; std::vector<std::vector<double> > fchLengths; double denomj = (numberOfModelFrames_ - 1.0); for (int i = 0; i < numberOfModelFrames_; i++) { std::vector<double> cLengths; double time = ((double) i) / denomj; Cmiss_field_cache_set_time(fieldCache, time); #ifdef printcoord std::cout<<"Frame "<<i<<"\t"<<time<<"\t"<<mySegments->at(0).xia[2]<<std::endl; #endif for (int j = 0; j < numSegments; j++) { WallSegment& seg = mySegments->at(j); //The the lengths temp_array1[0] = temp_array1[1] = temp_array1[2] = 0.0; temp_array2[0] = temp_array2[1] = temp_array2[2] = 0.0; //Since cmiss id starts at 1 subtract 1 from seg.elemeid? //Note that accessing some computed field (those that involve gradients), with multiple versions leads to gradient set to 0 warning Cmiss_field_cache_set_mesh_location(fieldCache, elements[seg.elementida - 1], 3, seg.xia); Cmiss_field_evaluate_real(field, fieldCache, 3, temp_array1); Cmiss_field_cache_set_mesh_location(fieldCache, elements[seg.elementidb - 1], 3, seg.xib); Cmiss_field_evaluate_real(field, fieldCache, 3, temp_array2); Point3D p1(temp_array1); Point3D p2(temp_array2); double dist = p1.distance(p2); #ifdef printcoord { int nodeCtr = (j / 8) * 9 + j % 8; Cmiss_field_cache_set_node(fieldCache, myNodes[Nodes[nodeCtr]]); temp_array1[0] = temp_array1[1] = temp_array1[2] = 0.0; Cmiss_field_evaluate_real(field, fieldCache, 3, temp_array1); Point3D p3(temp_array1); Cmiss_field_cache_set_node(fieldCache, myNodes[Nodes[nodeCtr + 1]]); temp_array1[0] = temp_array1[1] = temp_array1[2] = 0.0; Cmiss_field_evaluate_real(field, fieldCache, 3, temp_array1); Point3D p4(temp_array1); std::cout << p1 << "\t" << p2 << " = " << dist << "\t:\t Value at " << Nodes[nodeCtr] + 1 << "\t" << p3 << "\t" << p1.distance(p3) << "\t" << Nodes[nodeCtr + 1] + 1 << "\t" << p4 << "\t" << p2.distance(p4) << "\t distance \t " << p3.distance(p4) << std::endl; } #endif cLengths.push_back(dist); } for (int segc = 0; segc < numSegments / 8; segc++) { int offset = segc * 8; std::vector<double> sLengths; sLengths.push_back(cLengths[0 + offset] + (1 / 3.0 - 1 / 4.0) * 4 * cLengths[1 + offset]); sLengths.push_back((1.0 - (1 / 3.0 - 1 / 4.0)) * 4 * cLengths[1 + offset] + (2 / 3.0 - 1 / 2.0) * 4 * cLengths[2 + offset]); sLengths.push_back((1.0 - (2 / 3.0 - 1 / 2.0)) * 4 * cLengths[2 + offset] + cLengths[3 + offset]); sLengths.push_back(cLengths[4 + offset] + (1.0 - (2 / 3.0 - 1 / 2.0)) * 4 * cLengths[5 + offset]); sLengths.push_back((2 / 3.0 - 1 / 2.0) * 4 * cLengths[5 + offset] + (1.0 - (1 / 3.0 - 1 / 4.0)) * 4 * cLengths[6 + offset]); sLengths.push_back((1 / 3.0 - 1 / 4.0) * 4 * cLengths[6 + offset] + cLengths[7 + offset]); if (segc == 0) aplaxLengths.push_back(sLengths); else if (segc == 1) tchLengths.push_back(sLengths); else fchLengths.push_back(sLengths); } } std::vector<double> avgStrains(numberOfModelFrames_, 0.0); for (int segc = 0; segc < numSegments / 8; segc++) { std::vector<std::vector<double> > dstrains; std::vector<std::vector<double> > distances; if (segc == 0) distances = aplaxLengths; else if (segc == 1) distances = tchLengths; else if (segc == 2) distances = fchLengths; std::vector<double>& initStrain = distances[0]; for (int frame = 1; frame < numberOfModelFrames_; frame++) { //Compute Strains std::vector<double>& curStrainLengths = distances[frame]; std::vector<double> curStrain; double c = 0; unsigned int ulimit = initStrain.size(); for (int j = 0; j < ulimit; j++) { c = 100.0 * (curStrainLengths[j] - initStrain[j]) / initStrain[j]; curStrain.push_back(c); } dstrains.push_back(curStrain); } std::vector<std::string> strainSeries; for (int j = 0; j < initStrain.size(); j++) { std::ostringstream ss; ss << 0.0; //For init step int denom = numberOfModelFrames_ - 1; double maxStrain = dstrains[denom - 1][j]; //Note that frame goes from 1 to heart.numberOfModelFrames_ when computing strain //so shift down by 1 for (int i = 0; i < denom; i++) { //Compute Strains //Drift compensate double stc = dstrains[i][j] - (i + 1) * maxStrain / denom; ss << "," << stc; avgStrains[i] += stc; } strainSeries.push_back(ss.str()); } if (segc == 0) { strains[2 - 1] = strainSeries[5]; strains[8 - 1] = strainSeries[4]; strains[17 - 1] = strainSeries[3]; strains[18 - 1] = strainSeries[2]; strains[11 - 1] = strainSeries[1]; strains[5 - 1] = strainSeries[0]; } else if (segc == 2) { strains[3 - 1] = strainSeries[0]; strains[9 - 1] = strainSeries[1]; strains[14 - 1] = strainSeries[2]; strains[16 - 1] = strainSeries[3]; strains[12 - 1] = strainSeries[4]; strains[6 - 1] = strainSeries[5]; } else if (segc == 1) { strains[4 - 1] = strainSeries[0]; strains[10 - 1] = strainSeries[1]; strains[15 - 1] = strainSeries[2]; strains[13 - 1] = strainSeries[3]; strains[7 - 1] = strainSeries[4]; strains[1 - 1] = strainSeries[5]; } } #ifdef printcoord std::cout << "Linear 3D " << fieldName << std::endl; for (int i = 1; i < 100; i++) Cmiss_node_destroy(&myNodes[i]); #endif //Add the average strain //Num strain segments depends on the number of active segments (6 strain segments per view, which has 8 active segments) double denom = (numSegments / 8) * 6; std::ostringstream ss; ss << 0.0; //For init step for (int i = 0; i < numberOfModelFrames_ - 1; i++) { //Compute the Average ss << "," << avgStrains[i] / denom; } strains[18] = ss.str(); //Check if model PGS should be calculated if (computeModelPGS) { double max = fabs(avgStrains[0]); int idx = 0; for (int i = 1; i < numberOfModelFrames_ - 1; i++) { if (fabs(avgStrains[i]) > max) { max = fabs(avgStrains[i]); idx = i; } } modelPGS = avgStrains[idx] / denom; computeModelPGS = false; //set it so that it is not computed in subsequent calls } Cmiss_field_destroy(&field); return strains; }
std::vector<std::string> StrainMeasures::getRadialStrains(double wall_xi, ViewTypeEnum type) { std::vector<std::string> strains(18, ""); std::vector<double> avgStrains(numberOfModelFrames_, 0.0); std::ostringstream strain; //Note with respect to the model apex base is x-axis //choose y-z as xy //Compute the XI values for the circles const int allelemIds[][6][3] = { { { 47, 0, 0 }, { 46, 15, 31 }, { 14, 30, 46 }, { 45, 0, 0 }, { 48, 13, 29 }, { 16, 32, 48 } }, { { 43, 0, 0 }, { 42, 11, 27 }, { 14, 30, 46 }, { 41, 0, 0 }, { 44, 9, 25 }, { 12, 28, 44 } }, { { 39, 0, 0 }, { 38, 7, 23 }, { 14, 30, 46 }, { 37, 0, 0 }, { 40, 5, 21 }, { 8, 24, 40 } } }; const double elemStarts[][3] = { { 0, 0, 0 }, { 0.5, 0, 0 }, { 0.0, 0, 0 }, { 0, 0, 0 }, { 0.5, 0, 0 }, { 0, 0, 0 } }; const double elemEnds[][3] = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 0.5 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 0.5 } }; double discretization = 0.02; int typedepth = 0; if (type == SAXAPEX) typedepth = 2; else if (type == SAXMID) typedepth = 1; double depth = 0.0; //Get the central cross section std::vector<std::vector<double*> > eCPTS; std::vector<std::vector<int> > eELEM; for (int elemDepth = 0; elemDepth < 6; elemDepth++) { std::vector<double*> cpts; std::vector<int> cel; for (int eid = 0; eid < 3; eid++) { if (allelemIds[typedepth][elemDepth][eid] > 0) { int elemID = allelemIds[typedepth][elemDepth][eid] - 1; for (double xs = elemStarts[elemDepth][eid]; xs < elemEnds[elemDepth][eid]; xs += discretization) { Point3D xiCoord(xs, depth, wall_xi); cpts.push_back(xiCoord.ToArray()); cel.push_back(elemID); } } } eCPTS.push_back(cpts); eELEM.push_back(cel); } unsigned int nStrains = eCPTS.size(); for (int ns = 0; ns < nStrains; ns++) { std::vector<double*>& cpts = eCPTS[ns]; std::vector<int>& cel = eELEM[ns]; unsigned int npts = cpts.size(); std::vector<double> circums; for (int frame = 0; frame < numberOfModelFrames_; frame++) { double time = ((double) frame) / (numberOfModelFrames_ - 1.0); Cmiss_field_cache_set_time(fieldCache, time); //Compute the circle coordinates std::vector<Point3D> pts; double coord[3]; for (int j = 0; j < npts; j++) { Cmiss_field_cache_set_mesh_location(fieldCache, elements[cel[j]], 3, cpts[j]); Cmiss_field_evaluate_real(coordianteField, fieldCache, 3, coord); coord[1] = 0.0; pts.push_back(Point3D(coord[0], coord[1], coord[2])); } double distance = 0; for (int j = 1; j < npts; j++) { distance += pts[j - 1].distance(pts[j]); } circums.push_back(distance); } //Free mem for (int j = 0; j < npts; j++) { delete[] cpts[j]; } double initValue = circums[0]; strain.str(""); for (int frame = 0; frame < numberOfModelFrames_; frame++) { double stv = (circums[frame] - initValue) / initValue; strain << stv << ","; avgStrains[frame] += stv; } std::string lvstr = strain.str(); strains[ns] = (lvstr.substr(0, lvstr.length() - 1)); } //Push the average strain strain.str(""); for (int frame = 0; frame < numberOfModelFrames_; frame++) { strain << avgStrains[frame] / numberOfModelFrames_ << ","; } std::string lvstr = strain.str(); strains[17] = (lvstr.substr(0, lvstr.length() - 1)); //Location of average strain return strains; }
std::string StrainMeasures::getCircumferentialStrain(double wall_xi, ViewTypeEnum type) { std::ostringstream strain; //Note with respect to the model apex base is x-axis //choose y-z as xy //Compute the XI values for the circles // xi x(1 inc),height(1 dec),y(=xi) const int elemIds[][12] = { { 14, 30, 46, 15, 31, 47, 16, 32, 48, 13, 29, 45 }, { 10, 26, 42, 11, 27, 13, 12, 28, 44, 9, 25, 41 }, { 6, 22, 38, 7, 23, 39, 8, 24, 40, 5, 21, 37 }, { 2, 18, 34, 3, 19, 35, 4, 20, 36, 1, 17, 33 } }; double discretization = 0.02; int elemDepth = 2; double depth = 0.0; switch (type) { case SAXAPEX: { elemDepth = 2; depth = 0.5; break; } case SAXMID: { elemDepth = 1; depth = 0.5; break; } case SAXBASE: { elemDepth = 0; depth = 0.01; break; } } std::vector<double*> cpts; std::vector<int> cel; for (int eid = 0; eid < 12; eid++) { int elemID = elemIds[elemDepth][eid] - 1; for (double xs = 0.0; xs < 1.0; xs += discretization) { Point3D xiCoord(xs, depth, wall_xi); cpts.push_back(xiCoord.ToArray()); cel.push_back(elemID); } } unsigned int npts = cpts.size(); std::vector<double> circums; for (int frame = 0; frame < numberOfModelFrames_; frame++) { double time = ((double) frame) / (numberOfModelFrames_ - 1.0); Cmiss_field_cache_set_time(fieldCache, time); //Compute the circle coordinates std::vector<Point3D> pts; double coord[3]; for (int j = 0; j < npts; j++) { Cmiss_field_cache_set_mesh_location(fieldCache, elements[cel[j]], 3, cpts[j]); Cmiss_field_evaluate_real(coordianteField, fieldCache, 3, coord); coord[1] = 0.0; pts.push_back(Point3D(coord[0], coord[1], coord[2])); } LVChamberCircle circle(pts); circums.push_back(circle.getCircumference()); } //Free mem for (int j = 0; j < npts; j++) { delete[] cpts[j]; } double initValue = circums[0]; for (int frame = 0; frame < numberOfModelFrames_; frame++) { strain << (circums[frame] - initValue) / initValue << ","; } std::string lvstr = strain.str(); //Remove the last "," seperator return lvstr.substr(0, lvstr.length() - 1); }
std::string StrainMeasures::getLVVolume(double xi) { //Compute the LV circles std::vector<std::vector<Point3D> > circleXI; std::vector<std::vector<int> > circleElem; std::ostringstream lvVolume; //Note with respect to the model apex base is x-axis //choose y-z as xy //Compute the XI values for the circles // xi x(1 inc),height(1 dec),y(=xi) const int elemIds[][12] = { { 14, 30, 46, 15, 31, 47, 16, 32, 48, 13, 29, 45 }, { 10, 26, 42, 11, 27, 13, 12, 28, 44, 9, 25, 41 }, { 6, 22, 38, 7, 23, 39, 8, 24, 40, 5, 21, 37 }, { 2, 18, 34, 3, 19, 35, 4, 20, 36, 1, 17, 33 } }; double discretization = 0.05; for (int elemDepth = 0; elemDepth < 4; elemDepth++) { for (double depth = 1.0; depth >= discretization; depth -= discretization) { std::vector<Point3D> cpts; std::vector<int> cel; for (int eid = 0; eid < 12; eid++) { int elemID = elemIds[elemDepth][eid] - 1; for (double xs = 0.0; xs < 1.0; xs += discretization) { cpts.push_back(Point3D(xs, depth, xi)); cel.push_back(elemID); } } circleXI.push_back(cpts); circleElem.push_back(cel); } } unsigned int numCircles = circleXI.size(); double minVolume = -1.0; //Compute Ejection fraction double endVolume = 0.0; //as using smallest and end volume for (int frame = 0; frame < numberOfModelFrames_; frame++) { double time = ((double) frame) / (numberOfModelFrames_ - 1.0); std::vector<LVChamberCircle> circles; Cmiss_field_cache_set_time(fieldCache, time); //Compute the circles for (int i = 0; i < numCircles; i++) { std::vector<Point3D>& circlexi = circleXI[i]; std::vector<int>& cel = circleElem[i]; std::vector<Point3D> cpts; unsigned int npts = circlexi.size(); double coord[3]; for (int j = 0; j < npts; j++) { double* xcoord = circlexi[j].ToArray(); Cmiss_field_cache_set_mesh_location(fieldCache, elements[cel[j]], 3, xcoord); Cmiss_field_evaluate_real(coordianteField, fieldCache, 3, coord); cpts.push_back(Point3D(coord[0], coord[1], coord[2])); delete[] xcoord; } circles.push_back(LVChamberCircle(cpts)); } //Compute the volume for the existing circles double volume = 0.0; numCircles = circles.size(); for (int i = 0; i < numCircles - 1; i++) { volume += circles[i].getVolume(circles[i + 1]); } if (minVolume < 0.0 || volume < minVolume) { minVolume = volume; } endVolume = volume; lvVolume << volume << ","; } if (xi < 0.001) { ejectionFraction = (endVolume - minVolume) / endVolume; } std::string lvstr = lvVolume.str(); //Remove the last "," seperator return lvstr.substr(0, lvstr.length() - 1); }
void ShortAxisFitting::optimize(const alglib::real_1d_array& x, double& func, void* ptr) { struct ShortAxisOptimizationInput* input = static_cast<struct ShortAxisOptimizationInput*>(ptr); Cmiss_field_module_id field_module = (input->field_module); std::vector<Cmiss_node_id>& cmiss_nodes(*(input->cmiss_nodes)); std::vector<double>& targetDeltas(*(input->targetDeltas)); Cmiss_field_id coordinate = (input->coordinates_rc); Cmiss_field_cache_id cache = (input->cache); double* initialSegmentLengths = input->initialSegmentLengths; int* saxNodes = input->saxNodes; int numberOfModelFrames = input->numberOfModelFrames; int NUMBER_OF_SEGMENTS = input->NUMBER_OF_SEGMENTS; int NUMBER_OF_SAX_NODES = input->NUMBER_OF_SAX_NODES; double** result = input->result; //This is expected to be preallocated for heap efficiency int* endoNodeIds = input->endoNodesIds; const int NUMBER_OF_ENDO_NODES = 48; //Ignore the apex int ctr = 0; double coord[3]; int frame = input->frame; std::vector<Point3D>& resetCoord(input->initEndoCoordinates->at(frame)); std::vector<Point3D>& initFrame(*input->initFrame); setThetaDelta(input, x); //Compute the theta error double thetaError = 0.0; //for (int frame = 0; frame < numberOfModelFrames; frame++) { double time = ((double) frame) / ((double) numberOfModelFrames); if (frame == (numberOfModelFrames - 1)) { time = 1.0; } Cmiss_field_cache_set_time(cache, time); std::vector<Point3D> sax; Point3D sax_centroid(0, 0, 0); for (int seg = 0; seg < NUMBER_OF_SAX_NODES; seg++) { Cmiss_field_cache_set_node(cache, cmiss_nodes[saxNodes[seg]]); Cmiss_field_evaluate_real(coordinate, cache, 3, coord); Point3D start(coord); sax.push_back(start); sax_centroid += start; } sax_centroid = sax_centroid * (1.0 / NUMBER_OF_SAX_NODES); double avg = 0.0; for (int seg = 0; seg < NUMBER_OF_SAX_NODES; seg++) { Vector3D trans = sax[seg] - sax_centroid; double denom = trans.x- initFrame[seg].x; double nuem = trans.z- initFrame[seg].z; double ltheta = atan2(nuem, denom); if(fabs(denom)<1.0e-6 && fabs(nuem)<1.0e-6){ ltheta = 0.0; } avg += ltheta; } avg /=NUMBER_OF_SAX_NODES; thetaError +=fabs(avg-targetDeltas[frame]); input->thetaError = avg; } //Compute the segment error getSegmentLengths(input); double segmentMatchError = input->segmentMatchError; func = segmentMatchError + thetaError; if(segmentMatchError>2.0) func = 1.0e+30; input->totalError = func; //Reset coordinates to original { Cmiss_field_module_begin_change(field_module); { double time = ((double) frame) / ((double) numberOfModelFrames); if (frame == (numberOfModelFrames - 1)) { time = 1.0; } Cmiss_field_cache_set_time(cache, time); for (int nc = 0; nc < NUMBER_OF_ENDO_NODES; nc++) { coord[0] = resetCoord[nc].x; coord[1] = resetCoord[nc].y; coord[2] = resetCoord[nc].z; Cmiss_field_cache_set_node(cache, cmiss_nodes[endoNodeIds[nc] - 1]); Cmiss_field_assign_real(coordinate, cache, 3, coord); } } Cmiss_field_module_end_change(field_module); } }
ShortAxisFitting::ShortAxisFitting(std::vector<std::string> mesh, std::vector<std::vector<Point3D> > markers) : inputMesh(mesh), saxMarkers(markers) { numberOfModelFrames_ = mesh.size(); cmiss_nodes.resize(98); //Load the mesh //Initialise cmgui and get context context_ = Cmiss_context_create("saxfit"); //This required for using the cmiss_context_execute_command Cmiss_context_enable_user_interface(context_, NULL); /**< Handle to the context */ Cmiss_region_id root_region = Cmiss_context_get_default_region(context_); std::string region_name = "heart"; // Create a heart region Cmiss_region_id heart_region = Cmiss_region_create_child(root_region, region_name.c_str()); // Read in the heart model spaced over the number of model frames for (unsigned int i = 0; i < numberOfModelFrames_ - 1; i++) { double time = static_cast<double>(i) / numberOfModelFrames_; Cmiss_stream_information_id stream_information = Cmiss_region_create_stream_information(root_region); Cmiss_stream_information_region_id stream_information_region = Cmiss_stream_information_cast_region(stream_information); Cmiss_stream_resource_id stream_resource = Cmiss_stream_information_create_resource_memory_buffer(stream_information, mesh[i].c_str(), mesh[i].length()); Cmiss_stream_information_region_set_resource_attribute_real(stream_information_region, stream_resource, CMISS_STREAM_INFORMATION_REGION_ATTRIBUTE_TIME, time); Cmiss_region_read(root_region, stream_information); Cmiss_stream_resource_destroy(&stream_resource); Cmiss_stream_information_destroy(&stream_information); Cmiss_stream_information_region_destroy(&stream_information_region); } // Wrap the end point add another set of nodes at time 1.0 { Cmiss_stream_information_id stream_information = Cmiss_region_create_stream_information(root_region); Cmiss_stream_information_region_id stream_information_region = Cmiss_stream_information_cast_region(stream_information); Cmiss_stream_resource_id stream_resource = Cmiss_stream_information_create_resource_memory_buffer(stream_information, mesh[0].c_str(), mesh[0].length()); int r = Cmiss_stream_information_region_set_resource_attribute_real(stream_information_region, stream_resource, CMISS_STREAM_INFORMATION_REGION_ATTRIBUTE_TIME, 1.0); Cmiss_region_read(root_region, stream_information); Cmiss_stream_resource_destroy(&stream_resource); Cmiss_stream_information_destroy(&stream_information); Cmiss_stream_information_region_destroy(&stream_information_region); } //Cmiss_region_id heart_region = Cmiss_region_find_child_by_name(root_region, region_name.c_str()); //Get the field module of the heart region field_module_ = Cmiss_region_get_field_module(heart_region); if (field_module_ != 0) { Cmiss_field_module_begin_change(field_module_); // 'coordinates' is an assumed field in // a rc coordinate system. coordinates_rc_ = Cmiss_field_module_find_field_by_name(field_module_, "coordinates"); //Create the cache cache = Cmiss_field_module_create_cache(field_module_); Cmiss_field_module_end_change(field_module_); //Get node handles Cmiss_nodeset_id nodeset = Cmiss_field_module_find_nodeset_by_name(field_module_, "cmiss_nodes"); Cmiss_node_iterator_id nodeIterator = Cmiss_nodeset_create_node_iterator(nodeset); Cmiss_node_id node = Cmiss_node_iterator_next(nodeIterator); if (node != 0) { while (node) { int node_id = Cmiss_node_get_identifier(node); cmiss_nodes[node_id - 1] = node; node = Cmiss_node_iterator_next(nodeIterator); } } Cmiss_nodeset_destroy(&nodeset); Cmiss_node_iterator_destroy(&nodeIterator); int endo[] = { 55, 57, 71, 73, 66, 67, 69, 60, 61, 63, 52, 53, 54, 56, 70, 72, 64, 65, 68, 58, 59, 62, 50, 51, 77, 84, 85, 81, 82, 83, 78, 79, 80, 74, 75, 76, 89, 96, 97, 93, 94, 95, 90, 91, 92, 86, 87, 88, 98 }; memcpy(endoNodeIds, endo, sizeof(int) * 49); //int sax[] = { 73, 74, 75, 76, 83, 84, 80, 81, 82, 77, 78, 79 }; //int sax[] = { 79, 78, 77, 82, 81, 80, 84, 83, 76, 75, 74, 73 }; int sax[] = { 80, 81, 82, 77, 78, 79, 73, 74, 75, 76, 83, 84 }; memcpy(saxNodes, sax, sizeof(int) * NUMBER_OF_SAX_NODES); segmentNodes = new double*[24]; for (int i = 0; i < 24; i++) { segmentNodes[i] = new double[2]; } //Store the initial endo coordinates const int NUMBER_OF_ENDO_NODES = 48; //Skip apex double coord[3]; for(int frame = 0;frame<numberOfModelFrames_;frame++){ std::vector<Point3D> frameCoords; Cmiss_field_module_begin_change(field_module_); { double time = ((double) frame) / ((double) numberOfModelFrames_); if (frame == (numberOfModelFrames_ - 1)) { time = 1.0; } Cmiss_field_cache_set_time(cache, time); for (int nc = 0; nc < NUMBER_OF_ENDO_NODES; nc++) { Cmiss_field_cache_set_node(cache, cmiss_nodes[endoNodeIds[nc] - 1]); Cmiss_field_evaluate_real(coordinates_rc_, cache, 3, coord); Point3D start(coord); frameCoords.push_back(start); } initEndoCoordinates.push_back(frameCoords); } Cmiss_field_module_end_change(field_module_); } //Set the segment node ids segmentNodes[0][0] = aplaxNodes0; segmentNodes[0][1] = aplaxNodes1; segmentNodes[1][0] = aplaxNodes1; segmentNodes[1][1] = aplaxNodes2; segmentNodes[2][0] = aplaxNodes2; segmentNodes[2][1] = aplaxNodes3; segmentNodes[3][0] = aplaxNodes3; segmentNodes[3][1] = aplaxNodes4; segmentNodes[4][0] = aplaxNodes4; segmentNodes[4][1] = aplaxNodes5; segmentNodes[5][0] = aplaxNodes5; segmentNodes[5][1] = aplaxNodes6; segmentNodes[6][0] = aplaxNodes6; segmentNodes[6][1] = aplaxNodes7; segmentNodes[7][0] = aplaxNodes7; segmentNodes[7][1] = aplaxNodes8; segmentNodes[8][0] = tchNodes0; segmentNodes[8][1] = tchNodes1; segmentNodes[9][0] = tchNodes1; segmentNodes[9][1] = tchNodes2; segmentNodes[10][0] = tchNodes2; segmentNodes[10][1] = tchNodes3; segmentNodes[11][0] = tchNodes3; segmentNodes[11][1] = tchNodes4; segmentNodes[12][0] = tchNodes4; segmentNodes[12][1] = tchNodes5; segmentNodes[13][0] = tchNodes5; segmentNodes[13][1] = tchNodes6; segmentNodes[14][0] = tchNodes6; segmentNodes[14][1] = tchNodes7; segmentNodes[15][0] = tchNodes7; segmentNodes[15][1] = tchNodes8; segmentNodes[16][0] = fchNodes0; segmentNodes[16][1] = fchNodes1; segmentNodes[17][0] = fchNodes1; segmentNodes[17][1] = fchNodes2; segmentNodes[18][0] = fchNodes2; segmentNodes[18][1] = fchNodes3; segmentNodes[19][0] = fchNodes3; segmentNodes[19][1] = fchNodes4; segmentNodes[20][0] = fchNodes4; segmentNodes[20][1] = fchNodes5; segmentNodes[21][0] = fchNodes5; segmentNodes[21][1] = fchNodes6; segmentNodes[22][0] = fchNodes6; segmentNodes[22][1] = fchNodes7; segmentNodes[23][0] = fchNodes7; segmentNodes[23][1] = fchNodes8; //Compute the segment lengths initialSegmentLengths = new double[NUMBER_OF_SEGMENTS * numberOfModelFrames_]; ShortAxisOptimizationInput input; input.NUMBER_OF_SEGMENTS = NUMBER_OF_SEGMENTS; input.cache = cache; input.cmiss_nodes = &cmiss_nodes; input.coordinates_rc = coordinates_rc_; input.result = &initialSegmentLengths; input.numberOfModelFrames = numberOfModelFrames_; input.initialSegmentLengths = NULL; input.segmentNodes = segmentNodes; getSegmentLengths(&input); //Compute the average rotation that of the sax markers std::vector<Point3D>& iptCoord(saxMarkers[0]); unsigned int numSaxMarkers = iptCoord.size(); Point3D saxCentroid(0, 0, 0); for (int i = 0; i < numSaxMarkers; i++) { saxCentroid += iptCoord[i]; } saxCentroid = saxCentroid*(-1.0/numSaxMarkers); initFrame = iptCoord; for (int i = 0; i < numSaxMarkers; i++) { initFrame[i]+=saxCentroid; } for(int frame = 0;frame<numberOfModelFrames_;frame++){ std::vector<Point3D>& ipCoord(saxMarkers[frame]); unsigned int numSaxMarkers = ipCoord.size(); Point3D saxcentroid(0, 0, 0); for (int i = 0; i < numSaxMarkers; i++) { saxcentroid += ipCoord[i]; } saxcentroid = saxcentroid*(-1.0/numSaxMarkers); std::vector<Point3D> currentFrame(ipCoord); for (int i = 0; i < numSaxMarkers; i++) { currentFrame[i]+=saxcentroid; } double avgAngle = 0.0; for (int i = 0; i < numSaxMarkers; i++) { avgAngle += (atan2(currentFrame[i].z-initFrame[i].z,currentFrame[i].x-initFrame[i].x)); } avgAngle /=numSaxMarkers; targetDeltas.push_back(avgAngle); std::cout<<frame<<"\t"<<avgAngle*180/M_PI<<std::endl; } //The initFrame markers should correspond to the initFrame of the mesh as that is what is used in the comparisons initFrame.clear(); Point3D sax_centroid(0, 0, 0); for (int seg = 0; seg < NUMBER_OF_SAX_NODES; seg++) { Cmiss_field_cache_set_node(cache, cmiss_nodes[saxNodes[seg]]); Cmiss_field_evaluate_real(coordinates_rc_, cache, 3, coord); Point3D start(coord); initFrame.push_back(start); sax_centroid += start; } sax_centroid = sax_centroid * (-1.0 / NUMBER_OF_SAX_NODES); for (int seg = 0; seg < NUMBER_OF_SAX_NODES; seg++) { initFrame[seg] += sax_centroid; } } else { std::cout << "--- No field module for heart region!!! (Short Axis Fitting)"; std::cout << "No field module " << std::endl; throw -1; } Cmiss_region_destroy(&heart_region); Cmiss_region_destroy(&root_region); }
void ShortAxisFitting::fit() { //Compute the segment lengths double *tempSpace = new double[NUMBER_OF_SEGMENTS * numberOfModelFrames_]; memcpy(tempSpace, initialSegmentLengths, sizeof(double) * NUMBER_OF_SEGMENTS * numberOfModelFrames_); ShortAxisOptimizationInput* input = new struct ShortAxisOptimizationInput; input->numberOfModelFrames = numberOfModelFrames_; input->NUMBER_OF_SEGMENTS = NUMBER_OF_SEGMENTS; input->NUMBER_OF_SAX_NODES = NUMBER_OF_SAX_NODES; input->field_module = field_module_; input->coordinates_rc = coordinates_rc_; input->cache = cache; input->cmiss_nodes = &cmiss_nodes; input->targetDeltas = &targetDeltas; input->endoNodesIds = endoNodeIds; input->segmentNodes = segmentNodes; input->saxNodes = saxNodes; input->initialSegmentLengths = initialSegmentLengths; input->result = &tempSpace; input->segmentMatchError = 0.0; input->initFrame = &initFrame; input->initEndoCoordinates = &initEndoCoordinates; int nodegroups[][12] = { {aplaxNodes0,aplaxNodes8,tchNodes0,tchNodes8,fchNodes0,fchNodes8,aplaxtchNode00,aplaxtchNode88,fchaplaxNode00,fchaplaxNode88,fchtchNode08,fchtchNode80}, {aplaxNodes1,aplaxNodes7,tchNodes1,tchNodes7,fchNodes1,fchNodes7,aplaxtchNode11,aplaxtchNode77,fchaplaxNode11,fchaplaxNode77,fchtchNode17,fchtchNode71}, {aplaxNodes2,aplaxNodes6,tchNodes2,tchNodes6,fchNodes2,fchNodes6,aplaxtchNode22,aplaxtchNode66,fchaplaxNode22,fchaplaxNode66,fchtchNode26,fchtchNode62}, {aplaxNodes3,aplaxNodes5,tchNodes3,tchNodes5,fchNodes3,fchNodes5,aplaxtchNode33,aplaxtchNode55,fchaplaxNode33,fchaplaxNode55,fchtchNode35,fchtchNode53} }; // These variables define stopping conditions for the optimizer. // // We use very simple condition - |g|<=epsg // //Note that we do not want decimal accuracy, also the minimization problem never seems //to reduce the error to zero, rather the order is in 10000.00 double epsg = 0.10; double epsf = 0; double epsx = 0; double epso = 0.0010; double epsi = 0.0010; alglib::real_1d_array x; alglib::real_1d_array bndl; alglib::real_1d_array bndu; //Create the initial and boundary vectors int parameters = 4; double* tempValues = new double[parameters]; for (int i = 0; i < parameters; i++) { tempValues[i] = -0.25; } bndl.setcontent(parameters, tempValues); for (int i = 0; i < parameters; i++) { tempValues[i] = +0.25; } bndu.setcontent(parameters, tempValues); alglib::minbleicstate state; alglib::minbleicreport rep; alglib::ae_int_t maxits = 0; // // This variable contains differentiation step // double diffstep = 1.0e-4; for (int frame = 0; frame < numberOfModelFrames_; frame++) { input->frame = frame; clock_t begin = clock(); tempValues[0] = 0.0; tempValues[2] = targetDeltas[frame]; tempValues[1] = -targetDeltas[frame]/2; tempValues[3] = -targetDeltas[frame]/2; x.setcontent(parameters,tempValues); //Compute the centroids { double coord[3]; double time = ((double) frame) / ((double) numberOfModelFrames_); if (frame == (numberOfModelFrames_ - 1)) { time = 1.0; } Cmiss_field_cache_set_time(cache, time); //Compute the centroids Point3D centroids[4]; for(int sc=0;sc<4;sc++){ for(int nc = 0;nc<12;nc++){ Cmiss_field_cache_set_node(cache, cmiss_nodes[nodegroups[sc][nc]]); Cmiss_field_evaluate_real(coordinates_rc_, cache, 3, coord); Point3D start(coord); centroids[sc] += start; } input->centroids[sc] = centroids[sc]*(-1.0/12); } } // // Now we are ready to actually optimize something: // * first we create optimizer // * we add boundary constraints // * we tune stopping conditions // * and, finally, optimize and obtain results... // try { alglib::minbleiccreatef(x, diffstep, state); alglib::minbleicsetbc(state, bndl, bndu); alglib::minbleicsetinnercond(state, epsg, epsf, epsx); alglib::minbleicsetoutercond(state, epso, epsi); alglib::minbleicoptimize(state, optimize, NULL, input); alglib::minbleicresults(state, x, rep); setThetaDelta(input, x); { double coord[3]; { double time = ((double) frame) / ((double) numberOfModelFrames_); if (frame == (numberOfModelFrames_ - 1)) { time = 1.0; } Cmiss_field_cache_set_time(cache, time); std::vector<Point3D> sax; Point3D sax_centroid(0, 0, 0); for (int seg = 0; seg < NUMBER_OF_SAX_NODES; seg++) { Cmiss_field_cache_set_node(cache, cmiss_nodes[saxNodes[seg]]); Cmiss_field_evaluate_real(coordinates_rc_, cache, 3, coord); Point3D start(coord); sax.push_back(start); sax_centroid += start; } sax_centroid = sax_centroid * (1.0 / NUMBER_OF_SAX_NODES); double avg = 0.0; for (int seg = 0; seg < NUMBER_OF_SAX_NODES; seg++) { Vector3D trans = sax[seg] - sax_centroid; double denom = trans.x- initFrame[seg].x; double nuem = trans.z- initFrame[seg].z; double ltheta = atan2(nuem, denom); if(fabs(denom)<1.0e-6 && fabs(nuem)<1.0e-6){ ltheta = 0.0; } avg+=ltheta; } avg/=NUMBER_OF_SAX_NODES; std::cout << "Frame " << frame << "\t" << x.tostring(5)<<"\t Result "<<avg*180/M_PI<<"\t Target "<<targetDeltas[frame]*180/M_PI<< std::endl; } } } catch (alglib::ap_error& err) { std::cout << err.msg << std::endl; } clock_t end = clock(); double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; std::cout << "Optimization took " << elapsed_secs << std::endl; std::cout <<"Total Error "<< input->totalError << "\t segment error " << input->segmentMatchError << "\t thetaError " << input->thetaError << std::endl; std::cout<<"*******************************************************************"<<std::endl; } delete[] tempSpace; throw -1; }
int setTime(double time) { return Cmiss_field_cache_set_time(id, time); }