#include "stdafx.h" #include "TortuosityInput.h" using namespace std; /* disable all input windows so its clear to user that they shouldn't be used */ //void TortuosityInput::TortuosityInput(); short unsigned int tortDistribution(TortuosityDialog * TortDlg) { int i, totalnumber=0, num, res; int* dist; float temp, inc, size, largest = 0, smallest = 0xFFFF, harmean=0; fstream infile, infile2, outfile; char output[512]; char input[512]; res = TortDlg->field_output_dist_res_int; //open output file sprintf(output, "%sTortuosity\\%s_results_tortuosity.csv", TortDlg->field_directory_work_str, TortDlg->field_name_output_str); //do common header TortDlg->Write_Result_Header(output); outfile.open( output, ios::out | ios::app); if(!outfile.is_open()){ write_to_log("TortuosityDistribution: Could not open output file."); return 2; } outfile << ",XY,YZ,XZ" << endl; outfile << "ran,"; if (TortDlg->check_run_XY_cntrl.GetCheck()) outfile << "yes,"; else outfile << "no,"; if (TortDlg->check_run_YZ_cntrl.GetCheck()) outfile << "yes,"; else outfile << "no,"; if (TortDlg->check_run_XZ_cntrl.GetCheck()) outfile << "yes,"; else outfile << "no" << endl; outfile << "tracers," << TortDlg->GetIntValFromField(&(TortDlg->field_run_num_XY_cntrl)) <<","<< TortDlg->GetIntValFromField(&(TortDlg->field_run_num_YZ_cntrl)) <<","<< TortDlg->GetIntValFromField(&(TortDlg->field_run_num_XZ_cntrl)) << endl; outfile << "end depth," << TortDlg->field_end_depth_XY_int <<","<< TortDlg->field_end_depth_YZ_int <<","<< TortDlg->field_end_depth_XZ_int << endl; outfile << "tracers recorded," << TortDlg->field_num_save_tracers_XY_int <<","<<TortDlg->field_num_save_tracers_YZ_int <<","<<TortDlg->field_num_save_tracers_XZ_int << endl; //open input data file sprintf(input, "%sTortuosity\\%s_XY_data.txt", TortDlg->field_directory_work_str, TortDlg->field_name_output_str); infile.open( input, ios::in ); if(!infile.is_open()){ write_to_log("TortuosityDistribution: Could not open data input file."); return 1; } //scan file to find largest/smallest numbers, as well as total number of data points infile >> num >> temp; while ( !infile.eof() ) { totalnumber++; if(temp > largest) largest = temp; if(temp < smallest) smallest=temp; infile >> num >> temp; } infile.close(); //make sure that there was data present, if so proceed if (totalnumber > 0){ //special case of only one size being present if ( (largest - smallest) == 0 ){ //print the only result outfile << "Only the following tortuosity was present: " << largest << endl; outfile.close(); return 0; } dist = (int*)malloc(sizeof(int)*res); for(i=0; i < res; i++) dist[i] = 0; size = (float)(largest - smallest)/(float)res; //reopen file infile2.open( input, ios::in ); if(!infile2.is_open()){ write_to_log("TortuosityDistribution: Could not open input file."); return 3; } //2nd pass over data file, to fill distribution buckets infile2 >> num >> temp; while( !infile2.eof() ){ harmean = harmean + 1/temp; inc = size; i = 0; while(temp > (smallest + inc)){ i++; inc += size; } if (i >= res) dist[res-1]++; else if (i < 0) write_to_log("Tortuosity: Distribution: invalid bucket!"); else dist[i]++; infile2 >> num >> temp; } infile2.close(); //calc harmonic mean harmean = harmean/totalnumber; harmean = 1/harmean; //print results outfile << "Harmonic Mean:," << harmean << endl << endl; outfile << "Tortuosity Distribution,,," << "(See \"Data\" file for individual run results)" << endl; outfile << "Tortuosity,Occurrences\n"; for(i=0;i<res;i++){ outfile << (float)(smallest+i*(largest-smallest)/res) << "," << *(dist+i) << endl; } outfile.close(); free(dist); return 0; } // there was no data present, error? else { //print error into results file write_to_log("Output error, no data present for distribution creation."); outfile.close(); return 4; } } void disable_inputs(TortuosityDialog* TortDlg){ //common inputs disabled in dialog class //run settings TortDlg->check_run_XY_cntrl.EnableWindow(FALSE); TortDlg->check_run_YZ_cntrl.EnableWindow(FALSE); TortDlg->check_run_XZ_cntrl.EnableWindow(FALSE); TortDlg->field_run_num_XY_cntrl.EnableWindow(FALSE); TortDlg->field_run_num_YZ_cntrl.EnableWindow(FALSE); TortDlg->field_run_num_XZ_cntrl.EnableWindow(FALSE); TortDlg->check_runall_XY.EnableWindow(FALSE); TortDlg->check_runall_YZ.EnableWindow(FALSE); TortDlg->check_runall_XZ.EnableWindow(FALSE); TortDlg->field_end_depth_XY_cntrl.EnableWindow(FALSE); TortDlg->field_end_depth_YZ_cntrl.EnableWindow(FALSE); TortDlg->field_end_depth_XZ_cntrl.EnableWindow(FALSE); TortDlg->field_num_save_tracers_XY_cntrl.EnableWindow(FALSE); TortDlg->field_num_save_tracers_YZ_cntrl.EnableWindow(FALSE); TortDlg->field_num_save_tracers_XZ_cntrl.EnableWindow(FALSE); //advanced options TortDlg->check_enable_add_options.EnableWindow(FALSE); TortDlg->field_output_dist_res_cntrl.EnableWindow(FALSE); } /* re-enable the windows after an analysis run is done */ void enable_inputs(TortuosityDialog* TortDlg){ //enable the common inputs TortDlg->EnableCommonInputs(); //run settings TortDlg->check_run_XY_cntrl.EnableWindow(TRUE); TortDlg->check_run_YZ_cntrl.EnableWindow(TRUE); TortDlg->check_run_XZ_cntrl.EnableWindow(TRUE); TortDlg->field_run_num_XY_cntrl.EnableWindow(TRUE); TortDlg->field_run_num_YZ_cntrl.EnableWindow(TRUE); TortDlg->field_run_num_XZ_cntrl.EnableWindow(TRUE); if (TortDlg->check_enable_add_options.GetCheck()){ TortDlg->check_runall_XY.EnableWindow(TRUE); TortDlg->check_runall_YZ.EnableWindow(TRUE); TortDlg->check_runall_XZ.EnableWindow(TRUE); TortDlg->field_end_depth_XY_cntrl.EnableWindow(TRUE); TortDlg->field_end_depth_YZ_cntrl.EnableWindow(TRUE); TortDlg->field_end_depth_XZ_cntrl.EnableWindow(TRUE); TortDlg->field_num_save_tracers_XY_cntrl.EnableWindow(TRUE); TortDlg->field_num_save_tracers_YZ_cntrl.EnableWindow(TRUE); TortDlg->field_num_save_tracers_XZ_cntrl.EnableWindow(TRUE); } //advanced options TortDlg->check_enable_add_options.EnableWindow(TRUE); TortDlg->field_output_dist_res_cntrl.EnableWindow(TRUE); //flash for 3 seconds to alert user that we are done TortDlg->FlashWindowEx(FLASHW_TRAY, 3, 0); } UINT TortSetup(LPVOID pParam) { int tort_return = 0; DS_1b_cube *orig_ds_cube; char input_directory[512], work_directory[512]; char bin_base_name[512], data_base_name[512]; char input_base_name[512]; char data_out_prefix[512]; char data_out_name[512]; char tort_directory[512]; TortuosityDialog* TortDlg = (TortuosityDialog*) pParam; //disable all inputs for dialog disable_inputs(TortDlg); write_to_log("Tortuosity: inputs disabled, starting setup."); //initialize all variables and directories that are needed sprintf(input_directory, "%s", TortDlg->input_directory_name); sprintf(input_base_name, "%s%s", input_directory, TortDlg->input_file_name_cut); sprintf(work_directory, "%s", TortDlg->field_directory_work_str); sprintf(data_out_prefix, "%sTortuosity\\%s", work_directory, TortDlg->field_name_output_str); sprintf(tort_directory, "%sTortuosity", work_directory); if (!CreateDirectory(tort_directory,NULL)) //create a new Tortuosity directory if needed write_to_log("Tortuosity: 'Tortuosity' directory already exists, new one will not be created."); //read common input, which does everything and returns a cDS orig_ds_cube = TortDlg->Dlg_Input_to_cDS(); if (!orig_ds_cube){ TortDlg->txt_field_progress.SetWindowText("Invalid input file type detected."); enable_inputs(TortDlg); return 1; } /* start simulations... */ //into XY if(TortDlg->check_run_XY_cntrl.GetCheck()){ sprintf(data_out_name, "%s_XY", data_out_prefix); TortDlg->pbar_simulation_progress.SetPos(0); TortDlg->txt_field_progress.SetWindowText("Running tortuosity in XY plane..."); Tortuosity* XY_run = new Tortuosity(orig_ds_cube, TortDlg); { //write to log char logtext[512]; sprintf(logtext,"Tortuosity: Now running %d simulated pores in XY plane.", TortDlg->field_run_num_XY_int); write_to_log(logtext); } tort_return = XY_run->run_tortuosity(data_out_name, TortDlg->field_run_num_XY_int, (unsigned short)TortDlg->field_end_depth_XY_int, TortDlg->field_num_save_tracers_XY_int); delete XY_run; if ( tort_return != 0){ goto skip_to_error; } write_to_log("Tortuosity: Result file for XY run successfully created."); write_to_log("Tortuosity: XY analysis complete."); } ////into YZ // if(TortDlg->check_run_YZ_cntrl.GetCheck()){ // sprintf(data_out_name, "%s_YZ", data_out_prefix); // // TortDlg->pbar_simulation_progress.SetPos(0); // TortDlg->txt_field_progress.SetWindowText("Rotating image to YZ..."); // //rotate original memory cube 90 degrees so left YZ face is on top now // cDSinfo* rot_YZ_ds_info = rotate_cDS_XY_to_YZ(orig_ds_cube); // TortDlg->txt_field_progress.SetWindowText("Running tortuosity in YZ plane..."); // // { //write to log // char logtext[512]; // sprintf(logtext,"Tortuosity: Now running %d simulated pores in YZ plane.", TortDlg->field_run_num_YZ_int); // write_to_log(logtext); // } // // tort_return = run_tortuosity(rot_YZ_ds_info, TortDlg, data_out_name, TortDlg->field_run_num_YZ_int, // TortDlg->field_end_depth_YZ_int, TortDlg->field_num_save_tracers_YZ_int); // // if ( tort_return != 0){ // goto skip_to_error; // } // // //release memory // if (rot_YZ_ds_info) free_cDS(rot_YZ_ds_info); // // write_to_log("Tortuosity: Result file for XZ run successfully created."); // write_to_log("Tortuosity: XZ analysis complete."); // } ////into XZ // if(TortDlg->check_run_XZ_cntrl.GetCheck()){ // sprintf(data_out_name, "%s_XZ", data_out_prefix); // // TortDlg->pbar_simulation_progress.SetPos(0); // TortDlg->txt_field_progress.SetWindowText("Rotating image to XZ..."); // //rotate original memory cube 90 degrees so back XZ face is on top now // cDSinfo* rot_XZ_ds_info = rotate_cDS_XY_to_XZ(orig_ds_cube); // TortDlg->txt_field_progress.SetWindowText("Running tortuosity in XZ plane..."); // // { //write to log // char logtext[512]; // sprintf(logtext,"Tortuosity: Now running %d simulated pores in XZ plane.", TortDlg->field_run_num_XZ_int); // write_to_log(logtext); // } // // tort_return = run_tortuosity(rot_XZ_ds_info, TortDlg, data_out_name, TortDlg->field_run_num_XZ_int, // TortDlg->field_end_depth_XZ_int, TortDlg->field_num_save_tracers_XZ_int); // // if ( tort_return != 0){ // goto skip_to_error; // } // // //release memory // if (rot_XZ_ds_info) free_cDS(rot_XZ_ds_info); // // write_to_log("Tortuosity: Result file for XZ run successfully created."); // write_to_log("Tortuosity: XZ analysis complete."); // } skip_to_error: tortDistribution(TortDlg); // at least output something, maybe broke on 2nd run //error checking if ( tort_return != 0){ char logtext[512]; // incase the structure has no pore exit error if (tort_return == 1){ sprintf(logtext,"Tortuosity: Error: First BIN slice (%s%d) is all solid.", bin_base_name, 1); TortDlg->txt_field_progress.SetWindowText(logtext); write_to_log(logtext); } if (tort_return == 2){ sprintf(logtext,"Tortuosity: Error: No complete tracer path found after 100000 tries."); TortDlg->txt_field_progress.SetWindowText(logtext); write_to_log(logtext); } if (tort_return == 3){ sprintf(logtext,"Tortuosity: Error: Could not open tortuosity output data file (%s_TransData.txt).", data_base_name); TortDlg->txt_field_progress.SetWindowText(logtext); write_to_log(logtext); } if (tort_return == 4){ sprintf(logtext,"Tortuosity: Error: Could not allocate memory."); TortDlg->txt_field_progress.SetWindowText(logtext); write_to_log(logtext); } if (tort_return == 5){ sprintf(logtext,"Tortuosity: Warning: Tortuosity run was stopped by user before completion."); TortDlg->txt_field_progress.SetWindowText(logtext); TortDlg->StopConfirm(); } enable_inputs(TortDlg); return 1; } //delete RAW stack unless user specifies (if input is not BMP, also don't delete) if( (TortDlg->check_save_raw_stack.GetCheck() == FALSE) && (TortDlg->input_file_ext == INPUT_IS_BMP)){ // DeleteFile(info->raw_prefix); } //delete BIN stack unless user specifies (if input is BIN STACK, also don't delete) if( (TortDlg->check_save_cbin_stack.GetCheck() == FALSE) && (TortDlg->input_file_ext != INPUT_IS_CBIN_STACK)){ // DeleteFile(info->bin_prefix); } //restore original state if (orig_ds_cube) delete orig_ds_cube; TortDlg->txt_field_progress.SetWindowText("Analysis complete!"); enable_inputs(TortDlg); //AfxMessageBox("Tortuosity Analysis Done!"); return 0; }