int define_Computed_field_type_compose(struct Parse_state *state, void *field_modify_void, void *computed_field_compose_package_void) /******************************************************************************* LAST MODIFIED : 24 August 2006 DESCRIPTION : Converts <field> into type COMPUTED_FIELD_COMPOSE (if it is not already) and allows its contents to be modified. ==============================================================================*/ { int return_code; Computed_field_compose_package *computed_field_compose_package; Computed_field_modify_data *field_modify; struct Option_table *find_option_table, *option_table, *out_of_bounds_option_table; struct Set_Computed_field_conditional_data set_calculate_values_field_data, set_find_element_xi_field_data, set_texture_coordinates_field_data; ENTER(define_Computed_field_type_compose); if (state && (field_modify=(Computed_field_modify_data *)field_modify_void) && (computed_field_compose_package = (Computed_field_compose_package *) computed_field_compose_package_void)) { return_code = 1; Cmiss_mesh_id mesh = 0; char *search_group_name = 0; Cmiss_field_id calculate_values_field = 0; Cmiss_field_id find_element_xi_field = 0; Cmiss_field_id texture_coordinates_field = 0; char find_nearest_flag = 0; char find_exact_flag = 0; char use_point_five_when_out_of_bounds_flag = 0; char fail_when_out_of_bounds_flag = 0; int use_point_five_when_out_of_bounds = 0; int element_dimension = 0; /* Maintain the existing behaviour as the default */ int find_nearest = 0; /* get valid parameters for composite field */ if (field_modify->get_field()) { Computed_field_compose* compose_core = dynamic_cast<Computed_field_compose*>(field_modify->get_field()->core); if (compose_core) { return_code = compose_core->get_type( &calculate_values_field, &find_element_xi_field, &texture_coordinates_field, &mesh, &find_nearest, &use_point_five_when_out_of_bounds); if (mesh) { Cmiss_mesh_access(mesh); element_dimension = Cmiss_mesh_get_dimension(mesh); } } } if (return_code) { /* must access objects for set functions */ if (calculate_values_field) { ACCESS(Computed_field)(calculate_values_field); } if (find_element_xi_field) { ACCESS(Computed_field)(find_element_xi_field); } if (texture_coordinates_field) { ACCESS(Computed_field)(texture_coordinates_field); } option_table = CREATE(Option_table)(); Option_table_add_help(option_table, "The value of a compose field is found by evaluating the <texture_coordinates_field>, " "then searching for matching values of the <find_element_xi_field> in the elements of " "the <mesh> (alternatively specified by <group> and <element_dimension>) and then " "finally evaluating the <calculate_values_field> at this found location. You can " "specify the outcome if the matching values cannot be found in the mesh with " "<use_point_five_when_out_of_bounds> or <fail_when_out_of_bounds>. See examples " "a/resample_texture or a/create_slices where the compose field is used to find the " "equivalent coordinate in another element to evaluate a texture."); /* calculate_values_field */ set_calculate_values_field_data.computed_field_manager = field_modify->get_field_manager(); set_calculate_values_field_data.conditional_function = Computed_field_has_numerical_components; set_calculate_values_field_data.conditional_function_user_data = (void *)NULL; Option_table_add_entry(option_table, "calculate_values_field", &calculate_values_field, &set_calculate_values_field_data, set_Computed_field_conditional); Option_table_add_int_positive_entry(option_table,"element_dimension", &element_dimension); /* find_element_xi_field */ set_find_element_xi_field_data.computed_field_manager = field_modify->get_field_manager(); set_find_element_xi_field_data.conditional_function = Computed_field_has_numerical_components; set_find_element_xi_field_data.conditional_function_user_data = (void *)NULL; Option_table_add_entry(option_table, "find_element_xi_field", &find_element_xi_field, &set_find_element_xi_field_data, set_Computed_field_conditional); find_option_table=CREATE(Option_table)(); Option_table_add_char_flag_entry(find_option_table,"find_nearest", &find_nearest_flag); Option_table_add_char_flag_entry(find_option_table,"find_exact", &find_exact_flag); Option_table_add_suboption_table(option_table, find_option_table); /* group */ Option_table_add_string_entry(option_table, "group", &search_group_name, " GROUP_NAME"); // mesh Option_table_add_mesh_entry(option_table, "mesh", field_modify->get_region(), &mesh); /* texture_coordinates_field */ set_texture_coordinates_field_data.computed_field_manager = field_modify->get_field_manager(); set_texture_coordinates_field_data.conditional_function = Computed_field_has_numerical_components; set_texture_coordinates_field_data.conditional_function_user_data = (void *)NULL; Option_table_add_entry(option_table, "texture_coordinates_field", &texture_coordinates_field, &set_texture_coordinates_field_data, set_Computed_field_conditional); out_of_bounds_option_table=CREATE(Option_table)(); /* use_point_five_when_out_of_bounds */ Option_table_add_char_flag_entry(out_of_bounds_option_table, "use_point_five_when_out_of_bounds", &use_point_five_when_out_of_bounds_flag); Option_table_add_char_flag_entry(out_of_bounds_option_table, "fail_when_out_of_bounds", &fail_when_out_of_bounds_flag); Option_table_add_suboption_table(option_table, out_of_bounds_option_table); return_code = Option_table_multi_parse(option_table, state); if (return_code && !mesh) { mesh = Cmiss_field_module_find_mesh_by_dimension( field_modify->get_field_module(), element_dimension); if (search_group_name) { Cmiss_field_id group_field = Cmiss_field_module_find_field_by_name(field_modify->get_field_module(), search_group_name); Cmiss_field_group_id group = Cmiss_field_cast_group(group_field); Cmiss_field_element_group_id element_group = Cmiss_field_group_get_element_group(group, mesh); Cmiss_mesh_destroy(&mesh); mesh = Cmiss_mesh_group_base_cast(Cmiss_field_element_group_get_mesh(element_group)); Cmiss_field_element_group_destroy(&element_group); Cmiss_field_group_destroy(&group); Cmiss_field_destroy(&group_field); } } if (return_code && !mesh) { display_message(ERROR_MESSAGE, "You must specify a mesh (or element_dimension and optional group)."); return_code = 0; } if (return_code) { if (find_nearest_flag && find_exact_flag) { display_message(ERROR_MESSAGE, "Specify only one of find_nearest and find_exact"); return_code = 0; } if (find_nearest_flag) { find_nearest = 1; } else if (find_exact_flag) { find_nearest = 0; } if (use_point_five_when_out_of_bounds_flag && fail_when_out_of_bounds_flag) { display_message(ERROR_MESSAGE, "Specify only one of use_point_five_when_out_of_bounds " "and fail_when_out_of_bounds"); return_code = 0; } if (use_point_five_when_out_of_bounds_flag) { use_point_five_when_out_of_bounds = 1; } else if (fail_when_out_of_bounds_flag) { use_point_five_when_out_of_bounds = 0; } } if (return_code) { return_code = field_modify->update_field_and_deaccess( Computed_field_create_compose(field_modify->get_field_module(), texture_coordinates_field, find_element_xi_field, calculate_values_field, mesh, find_nearest, use_point_five_when_out_of_bounds)); } if (!return_code) { if ((!state->current_token) || (strcmp(PARSER_HELP_STRING, state->current_token)&& strcmp(PARSER_RECURSIVE_HELP_STRING, state->current_token))) { /* error */ display_message(ERROR_MESSAGE, "define_Computed_field_type_compose. Failed"); } } Cmiss_mesh_destroy(&mesh); if (calculate_values_field) { DEACCESS(Computed_field)(&calculate_values_field); } if (find_element_xi_field) { DEACCESS(Computed_field)(&find_element_xi_field); } if (search_group_name) { DEALLOCATE(search_group_name); } if (texture_coordinates_field) { DEACCESS(Computed_field)(&texture_coordinates_field); } DESTROY(Option_table)(&option_table); } } else { display_message(ERROR_MESSAGE, "define_Computed_field_type_compose. Invalid argument(s)"); return_code = 0; } LEAVE; return (return_code); } /* define_Computed_field_type_compose */
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; }
StrainMeasures::StrainMeasures(std::vector<std::string> mesh) : mySegments(NULL) { num_level_sets = 10; num_elements = 48; num_nodes = 98; elements.resize(num_elements); x_discret = 25; y_discret = 25; lagrangian = true; modelPGS = 0.0; computeModelPGS = false; ejectionFraction = 0.0; extraNodeStartID = 100000; LVMyocardialVolume* lvm = new LVMyocardialVolume(mesh); volumes = lvm->getMyocardialVolumes(); delete lvm; //Read the mesh context_ = Cmiss_context_create("strainmeasure"); /**< Handle to the context */ Cmiss_region_id root_region = Cmiss_context_get_default_region(context_); //This required for using the cmiss_context_execute_command Cmiss_context_enable_user_interface(context_, NULL); //Load the finite element mesh of the heart std::string region_name = "heart"; Cmiss_region_id heart_region = Cmiss_region_create_child(root_region, region_name.c_str()); //Get the field module of the heart region field_module = Cmiss_region_get_field_module(heart_region); fieldCache = Cmiss_field_module_create_cache(field_module); numberOfModelFrames_ = mesh.size(); double denom = numberOfModelFrames_ - 1; for (unsigned int i = 0; i < numberOfModelFrames_; i++) { double time = static_cast<double>(i) / denom; 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); } { //Define the necessary fields std::string referenceMesh = mesh[0]; //Change coordinate name to reference_coordinates boost::replace_all(referenceMesh, "1) coordinates", "1) reference_coordinates"); //Load the reference coordinates mesh 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, referenceMesh.c_str(), referenceMesh.length()); Cmiss_region_read(root_region, stream_information); Cmiss_stream_resource_destroy(&stream_resource); Cmiss_stream_information_destroy(&stream_information); } coordianteField = Cmiss_field_module_find_field_by_name(field_module, "reference_coordinates"); if (!coordianteField) { std::cout << "reference_coordinates field not found " << std::endl; } Cmiss_region_destroy(&heart_region); //#Calculate the strains Cmiss_field_module_define_field(field_module, "F", "gradient coordinate reference_coordinates field coordinates"); Cmiss_field_module_define_field(field_module, "F_transpose", "transpose source_number_of_rows 3 field F"); Cmiss_field_module_define_field(field_module, "C", "matrix_multiply number_of_rows 3 fields F_transpose F"); Cmiss_field_module_define_field(field_module, "principal_strains", "eigenvalues field C"); Cmiss_field_destroy(&coordianteField); //Assign the coordinates field to the handle for downstream use coordianteField = Cmiss_field_module_find_field_by_name(field_module, "coordinates"); //Define the fibre field { //Load the reference fibre data and reference coordinates { if (Cmiss_field_module_find_field_by_name(field_module, "fibres") == NULL) { 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, reffibre_exregion, reffibre_exregion_len); Cmiss_stream_resource_id stream_resource = Cmiss_stream_information_create_resource_memory_buffer(stream_information, humandtifibre_exregion, humandtifibre_exregion_len); Cmiss_region_read(root_region, stream_information); Cmiss_stream_resource_destroy(&stream_resource); Cmiss_stream_information_destroy(&stream_information); } //Define fibre field //#Calculate the deformed fibre axes Cmiss_field_module_define_field(field_module, "fibre_axes", "fibre_axes coordinate reference_coordinates fibre fibres"); Cmiss_field_module_define_field(field_module, "deformed_fibre_axes", "matrix_multiply number_of_rows 3 fields fibre_axes F_transpose"); Cmiss_field_module_define_field(field_module, "deformed_fibre", "composite deformed_fibre_axes.1 deformed_fibre_axes.2 deformed_fibre_axes.3"); Cmiss_field_module_define_field(field_module, "principal_fibre_strain1", "composite deformed_fibre_axes.1"); } } //Determine the myocardial volume //Get the element and node handles Cmiss_mesh_id cmiss_mesh = Cmiss_field_module_find_mesh_by_name(field_module, "cmiss_mesh_3d"); Cmiss_element_iterator_id elementIterator = Cmiss_mesh_create_element_iterator(cmiss_mesh); Cmiss_element_id element = Cmiss_element_iterator_next(elementIterator); while (element != NULL) { int elementId = Cmiss_element_get_identifier(element) - 1; //Cmiss numbering starts at 1 elements[elementId] = element; element = Cmiss_element_iterator_next(elementIterator); } Cmiss_element_iterator_destroy(&elementIterator); Cmiss_mesh_destroy(&cmiss_mesh); Cmiss_region_destroy(&root_region); }
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); }