Skip to content

Instantly share code, notes, and snippets.

@DylanLukes
Created March 17, 2011 20:33
Show Gist options
  • Save DylanLukes/875076 to your computer and use it in GitHub Desktop.
Save DylanLukes/875076 to your computer and use it in GitHub Desktop.
// 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