Created
March 17, 2011 20:33
-
-
Save DylanLukes/875076 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Reads in a set of raw data files, and outputs smoothed files. (lots of libdispatch magic) | |
#define SIGMA (50) | |
#define CONST_A (1 / sqrt(2 * pi * (pow(SIGMA, 2)))) | |
- (IBAction)smoothDataSets:(id)sender { | |
[openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger ret){ | |
if(ret == NSOKButton){ | |
// Generate a gaussian weight | |
int len = 6 * SIGMA + 1; | |
double weight[len]; | |
for(int i = 0; i < len; i++){ | |
weight[i] = CONST_A * exp(-1 * pow(i - (len/2), 2) | |
/ pow(2 * SIGMA, 2)); | |
} | |
// Apply to each file and then output appropriately. | |
dispatch_group_t smooth_group = dispatch_group_create(); | |
dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
for(NSURL *url in [openPanel URLs]){ | |
const char *in_path = [[url path] UTF8String]; | |
const char *out_path = [[[url URLByAppendingPathExtension:@"smoothed"] path] UTF8String]; | |
dispatch_group_async(smooth_group, global_queue, ^{ | |
// Open file for reading... | |
dispatch_io_t input_file = dispatch_io_create_with_path(DISPATCH_IO_STREAM, in_path, O_RDONLY, 0, dispatch_get_current_queue(), ^(int error) { | |
printf("Error while opening file for smoothing: %d", error); | |
}); | |
// Set low water mark to SIZE_MAX for no incomplete handlers | |
dispatch_io_set_low_water(input_file, SIZE_MAX); | |
// Create new file for writing... | |
dispatch_io_t output_file = dispatch_io_create_with_path(DISPATCH_IO_STREAM, out_path, O_RDWR | O_CREAT, 0, dispatch_get_current_queue(), ^(int error) { | |
if(error != 0){ | |
printf("Error creating file for writing for smoothing: %d", error); | |
} | |
}); | |
dispatch_io_read(input_file, 0, SIZE_MAX, dispatch_get_current_queue(), ^(bool done, dispatch_data_t data, int error) { | |
if (data == dispatch_data_empty) return; | |
const char *sim_data; size_t sim_data_len; | |
// Close the input file | |
dispatch_io_close(input_file, 0); | |
// Create source data | |
dispatch_data_t map_data = dispatch_data_create_map(data, (const void **)&sim_data, &sim_data_len); | |
// WARNING: NO SAFETY OR ERROR HANDLING BELOW. :( | |
// Get the number of items in the file... | |
// Confirm the meta data header is stuck on the top of the file | |
NSInteger num_items; | |
sscanf(sim_data, "# %ld\n", &num_items); | |
double *src_buf = malloc(num_items * sizeof(double)); | |
double *dst_buf = malloc(num_items * sizeof(double)); | |
// For each item to parse, search for a newline, then scan from there. | |
const char *p = sim_data; | |
NSInteger j; | |
for(int n = 0; n < num_items; n++){ | |
p = strchr(p, '\n') + sizeof(char); | |
sscanf(p, "%ld", &j); | |
sscanf(p, "%*ld %lf", &src_buf[j]); | |
} | |
dispatch_group_t gaussian_group = dispatch_group_create(); | |
#pragma mark SERIOUS MATH HERE | |
for(int i = 0; i < num_items; i++){ | |
dispatch_group_async(gaussian_group, dispatch_get_current_queue(), ^(void) { | |
// TODO: Apply gaussian transformation to each point, and then | |
// output data point to output_file. | |
// Data points too close to the sides are ignored | |
if(i < 3 * SIGMA || i > num_items - 3 * SIGMA){ | |
dst_buf[i] = src_buf[i]; | |
} | |
// Data points in the middle are smoothed by averaging the sum of the gaussian w/ the data points... | |
double sum = src_buf[i]; | |
for(int j = i - (3 * SIGMA), k = 0; i < i + (3 * SIGMA); j++, k++){ | |
sum += weight[k] * src_buf[j]; | |
} | |
double avg = sum / (6 * SIGMA + 1); | |
dst_buf[i] = avg; | |
}); | |
} | |
#pragma mark DONE WITH SERIOUS MATH | |
dispatch_group_notify(gaussian_group, dispatch_get_current_queue(), ^(void) { | |
NSLog(@"Outputing results of smoothing."); | |
char *str; | |
// Write header to dispatch_data | |
asprintf(&str, "# %ld\n", num_items); | |
dispatch_data_t data = dispatch_data_create(str, strlen(str), dispatch_get_current_queue(), DISPATCH_DATA_DESTRUCTOR_DEFAULT); | |
free(str); | |
// Write output to dispatch_data | |
for (NSInteger n = 0; n < num_items; n++) { | |
// Create data with this line | |
asprintf(&str, "%ld %lf\n", n, dst_buf[n]); | |
dispatch_data_t newdata = dispatch_data_create(str, strlen(str), dispatch_get_current_queue(), DISPATCH_DATA_DESTRUCTOR_DEFAULT); | |
free(str); | |
// Append it | |
dispatch_data_t olddata = data; | |
data = dispatch_data_create_concat(data, newdata); | |
dispatch_release(olddata); | |
dispatch_release(newdata); | |
} | |
dispatch_io_write(output_file, 0, data, dispatch_get_current_queue(), ^(bool done, dispatch_data_t data, int error) { | |
if (error != 0) { | |
NSLog(@"Error writing: %d", error); | |
} | |
if(done){ | |
free(src_buf); | |
free(dst_buf); | |
dispatch_io_close(output_file, 0); | |
NSLog(@"Smoothing and output finished on a file."); | |
} | |
}); | |
// Release resources and close everything up. We're done! | |
}); | |
dispatch_release(map_data); | |
dispatch_release(gaussian_group); | |
}); | |
}); | |
dispatch_group_notify(smooth_group, global_queue, ^{ | |
NSLog(@"All smoothing dispatched."); | |
}); | |
} | |
dispatch_release(smooth_group); | |
} | |
}]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment