void free_SMC_ABC_t(SMC_ABC_t *ABC) { if (ABC->oldPart) {free_particle_arr(ABC->oldPart); ABC->oldPart = NULL;} if (ABC->newPart) {free_particle_arr(ABC->newPart); ABC->newPart = NULL;} if (ABC->diffList) {free_double_arr(ABC->diffList); ABC->diffList = NULL;} if (ABC->obsSummary) {free_double_arr(ABC->obsSummary); ABC->obsSummary = NULL;} if (ABC->simulSummary) {free_double_arr(ABC->simulSummary); ABC->simulSummary = NULL;} if (ABC->peakHist) {free_hist_t(ABC->peakHist); ABC->peakHist = NULL;} if (ABC->sampArr) {free_sampler_arr(ABC->sampArr); ABC->sampArr = NULL;} if (ABC->hMap) {free_halo_map(ABC->hMap); ABC->hMap = NULL;} if (ABC->gMap) {free_gal_map(ABC->gMap); ABC->gMap = NULL;} if (ABC->kMap) {free_map_t(ABC->kMap); ABC->kMap = NULL;} if (ABC->nMap) {free_map_t(ABC->nMap); ABC->nMap = NULL;} if (ABC->transformer) {free_FFT_t(ABC->transformer); ABC->transformer = NULL;} if (ABC->peakList) {free_double_arr(ABC->peakList); ABC->peakList = NULL;} free(ABC); ABC = NULL; return; }
void free_particle_arr(particle_arr *part) { int i; if (part->array) { for (i=0; i<part->p; i++) {free_particle_t(part->array[i]); part->array[i] = NULL;} } if (part->mean) {free_double_arr(part->mean); part->mean = NULL;} gsl_matrix_free(part->cov); gsl_matrix_free(part->cov2); gsl_matrix_free(part->invCov); gsl_permutation_free(part->perm); free(part); return; }
/* * Finds the constant required to normalise the function to the given set of event * data. The check limit specifies the range of values that will be checked to find * the constant. Starts from 1 and goes up to check_limit with the given step. * Returns a negative value if something goes wrong. To get a good normaliser for * the actual function, it is probably best to use the number of subintervals equivalent * to the length of the interval divided by the time steps that lambda represents. * This is usually one time step. As an example, if lambda represents the number of * events in one second, and your interval time is 100 seconds, you should use 100 * intervals. A normaliser is required for functions estimated using the gaussian * kernel method due to the way that gaussians are summed. Dividing the values of * the estimated function by the return value of this function will give a function * that is on the same scale as the generating function. */ double _find_normaliser(void* f1, double_arr* events, double interval_start, double interval_end, double check_start, double check_limit, double step, int subintervals, char* type) { double normaliser = check_start; double best = -INFINITY; double best_normaliser = -INFINITY; int* bin_counts = sum_events_in_interval(events->data, events->len, interval_start, interval_end, subintervals); double* midpoints = get_interval_midpoints(interval_start, interval_end, subintervals); double_arr* function_values; if (strcmp(type, "gauss") == 0){ function_values = sum_gaussians_at_points((gauss_vector*) f1, midpoints, subintervals); } else if (strcmp(type, "base") == 0){ function_values = estimate_at_points((est_arr*) f1, midpoints, subintervals); } else { printf("Unknown type \"%s\"when finding normalisation constant.\n", type); exit(1); } while(normaliser <= check_limit){ double pmf_sum = sum_log_pdfs(bin_counts, function_values->data, normaliser, subintervals); // printf("Sum with normaliser %lf: %lf, current best %lf (%lf).\n", normaliser, pmf_sum, best, best_normaliser); if (pmf_sum > best) { best = pmf_sum; best_normaliser = normaliser; // printf("New best normaliser is %lf with a sum of %lf\n", best_normaliser, best); } // printf("total pmf is %lf, normaliser is %lf\n", pmf_sum, normaliser); normaliser += step; } free(midpoints); free(bin_counts); free_double_arr(function_values); return best_normaliser; }
/* * Computes the time delay between two functions f1 and f2. Requires data about the * event streams of which each of the functions is an estimate. f1 is the base function, * if there are more than two functions. This function is taken as the baseline against * which all other functions are compared, and so the time delay will be given relative to * it. The function splits the interval specified in the parameter file into a number of * bins, and calculates the number of events that fall into each bin. To calculate the time delay, * f2 is shifted relative to f1, starting at a negative shift and moving to a positive one. * The process is iterative, and the granularity of the estimate is defined by the step * specified in the parameter file. The estimate of the time delay is the point at which the * sum of the probability mass functions taken at a number of points along the combination of * the base function and the shifted function is minimised. In other words, the shift at * which the bin counts most closely match the lambda values taken from the functions * is the estimate returned. The functions are combined such that for all possible delays * in the range [-max_delay, max_delay], the same amount of data is gathered. */ double _estimate_delay_pmf(char* outfile, double_arr* base_events, double_arr* f2_events, void* f1, void* f2, double combine_start, double combine_interval, double combine_step, int num_bins, double start_delta, double end_delta, double max_delay, double delta_step, double normaliser, char* type, int output_switch) { // Always work on two streams int num_streams = 2; double combine_end = combine_start + combine_interval; double bin_length = (combine_end - combine_start)/num_bins; double current_delta = start_delta; // Set the initial values for our estimate double best_delta = -INFINITY; double best_value = -INFINITY; // We don't know which type we will get, so use a void pointer to store // it and cast later. void** store = NULL; if (strcmp(type, "gauss") == 0){ store = malloc(sizeof(gauss_vector*) * 2); store[0] = (gauss_vector*)f1; store[1] = (gauss_vector*)f2; } else if (strcmp(type, "base") == 0){ store = malloc(sizeof(est_arr*) * 2); store[0] = (est_arr*)f1; store[1] = (est_arr*)f2; } #ifdef VERBOSE printf("cstart %lf cend %lf cint %lf cstep %lf nbins %d startd %lf endd %lf maxd %lf dstep %lf norm %lf\n", combine_start, combine_end, combine_interval, combine_step, num_bins, start_delta, end_delta, max_delay, delta_step, normaliser); #endif double_arr* time_delay = init_double_arr(2); time_delay->data[0] = 0; double_multi_arr* combined = NULL; double_multi_arr* delay_pmfs = init_multi_array(2, (int)((end_delta - start_delta)/delta_step)+1); // PMF sums will be calculated for both streams. int* bin_counts1 = sum_events_in_interval(base_events->data, base_events->len, combine_start, combine_end, num_bins); int* bin_counts2 = sum_events_in_interval(f2_events->data, f2_events->len, combine_start, combine_end, num_bins); double* midpoints = get_interval_midpoints(combine_start, combine_end, num_bins); double* lambda_sums = malloc(sizeof(double) * num_bins); double* best_lambda_sums = malloc(sizeof(double) * num_bins); // How many bins need to be skipped to ensure that only the bins that are present in int skip_bins = (int) max_delay/bin_length; int i, j = 0; while (current_delta <= end_delta){ // get the combined function with the delay applied // compare the combined function to the bin counts of the stream by calculating the pmf for each interval // to do this, first get the bin counts. These will remain constant for the function. // then, calculate the interval times for each bin, which will be the same for each // sum the values of lambda within this interval at each time. This will be one lambda per second, probably, // since each lambda represents the number of arrivals per single time step // finally, find the poisson pmf of the two values - gsl_ran_poisson_pdf(bin count, lambda sum for bin) // printf("current delta %lf\n", current_delta); time_delay->data[1] = current_delta; if (strcmp(type, "gauss") == 0){ combined = combine_gauss_vectors((gauss_vector**)store, time_delay, combine_start, combine_end, combine_step, normaliser, num_streams); } else if (strcmp(type, "base") == 0){ combined = combine_functions((est_arr**)store, time_delay, combine_start, combine_interval, combine_step, num_streams); } else { printf("Unknown type for estimate \"%s\" when estimating delta.\n", type); exit(1); } for (i = 0; i < num_bins; ++i) { // find the sum of lambda values for each subinterval // The lambda sums must be normalised so that they are on the same scale as the bin counts. lambda_sums[i] = sum_array_interval(combined->data[0], combined->data[1], i * bin_length, (i + 1) * bin_length, 1, combined->lengths[0]); #ifdef VERBOSE printf("subinterval start %lf, subinterval end %lf\n", i * bin_length, (i + 1) * bin_length); printf("sum of lambdas in interval %lf\n", lambda_sums[i]); #endif } int s2_shift = (int)(ceil((max_delay - current_delta)/bin_length)); // printf("s2 shift is %d. Number of bins being checked %d\n", s2_shift, num_bins - 2 * skip_bins); #ifdef VERBOSE2 for (i = 0; i < num_bins - 2 * skip_bins; ++i) { printf("Counts 1 %d counts 2 %d, comparing %lf from 1 with %lf from 2, lambda is %lf\n", (bin_counts1+skip_bins)[i], (bin_counts2+s2_shift)[i], (midpoints+skip_bins)[i], (midpoints+s2_shift)[i], (lambda_sums+skip_bins)[i]); } #endif double total1 = sum_log_pdfs(bin_counts1 + skip_bins, lambda_sums + skip_bins, 1, num_bins - 2 * skip_bins); // need to shift bin_counts2 so that the correct intervals line up for the given delay double total2 = sum_log_pdfs(bin_counts2 + s2_shift, lambda_sums + skip_bins, 1, num_bins - 2 * skip_bins); double cumulative = total1 + total2; delay_pmfs->data[0][j] = current_delta; delay_pmfs->data[1][j] = cumulative; // printf("pmf sum is %lf\n", total); if (cumulative > best_value){ // printf("New value %lf is less than old %lf. guess updated to %lf\n", cumulative, best_value, current_delta); best_value = cumulative; best_delta = current_delta; memcpy(best_lambda_sums, lambda_sums, sizeof(double) * num_bins); } else { // printf("New value %lf is larger than old %lf. guess remains at %lf\n", cumulative, best_value, best_delta); } current_delta += delta_step; free_double_multi_arr(combined); j++; } if (outfile != NULL && output_switch != 0){ char* out = malloc(strlen(outfile) + strlen("_pmf_lambda.dat") + 5); if (output_switch >= 1){ sprintf(out, "%s_pmf_delay.dat", outfile); output_double_multi_arr(out, "w", delay_pmfs); } if (output_switch >= 2){ sprintf(out, "%s_pmf_lambda.dat", outfile); FILE *fp = fopen(out, "w"); for (i = 0; i < num_bins; ++i) { fprintf(fp, "%lf %lf\n", midpoints[i], best_lambda_sums[i]); } fclose(fp); sprintf(out, "%s_pmf_bins.dat", outfile); fp = fopen(out, "w"); for (i = 0; i < num_bins; ++i) { fprintf(fp, "%lf %d %d\n", midpoints[i], bin_counts1[i], bin_counts2[i]); } fclose(fp); } free(out); } free(midpoints); free(lambda_sums); free(best_lambda_sums); free(bin_counts1); free(bin_counts2); free(store); free_double_arr(time_delay); free_double_multi_arr(delay_pmfs); return best_delta; }