int main(void) { fftw_complex in[N0][N1][N2], out[N0][N1][N2], out2[N0][N1][N2]; /* double [2] */ fftw_plan p; int i0, i1, i2; p = fftw_plan_dft_3d(N0, N1, N2, &in[0][0][0], &out[0][0][0], FFTW_FORWARD, FFTW_ESTIMATE); for (i0 = 0; i0 < N0; i0++) for (i1 = 0; i1 < N1; i1++) for (i2 = 0; i2 < N2; i2++) { in[i0][i1][i2][0] = sin(2*M_PI*i0/N0) + 3*cos(6*M_PI*i1/N1); in[i0][i1][i2][1] = 5*cos(4*M_PI*i2/N2); } fftw_execute(p); ft3d(N0, N1, N2, &in[0][0][0], &out2[0][0][0]); for (i0 = 0; i0 < N0; i0++) for (i1 = 0; i1 < N1; i1++) for (i2 = 0; i2 < N2; i2++) if ( fabs(out[i0][i1][i2][0]) > 1e-3 || fabs(out[i0][i1][i2][1]) > 1e-3 || fabs(out2[i0][i1][i2][0]) > 1e-3 || fabs(out2[i0][i1][i2][1]) > 1e-3 ) printf("%6d %6d %6d: %20.10f %20.10f | %20.10f %20.10f\n", i0, i1, i2, out[i0][i1][i2][0], out[i0][i1][i2][1], out2[i0][i1][i2][0], out2[i0][i1][i2][1]); fftw_destroy_plan(p); fftw_cleanup(); return 0; }
void FFT_cleanup() { fftw_cleanup(); pthread_mutex_destroy(mutex); delete mutex; mutex = NULL; }
/** * Advection/diffusion example using an encapsulated IMEX sweeper. * * This example uses a vanilla SDC sweeper. * * @ingroup AdvectionDiffusion */ error_map run_vanilla_sdc(double abs_residual_tol, double rel_residual_tol=0.0) { SDC<> sdc; auto const nnodes = config::get_value<size_t>("num_nodes", 3); auto const ndofs = config::get_value<size_t>("spatial_dofs", 64); auto const quad_type = \ config::get_value<quadrature::QuadratureType>("nodes_type", quadrature::QuadratureType::GaussLegendre); auto quad = quadrature::quadrature_factory(nnodes, quad_type); auto factory = make_shared<encap::VectorFactory<double>>(ndofs); auto sweeper = make_shared<AdvectionDiffusionSweeper<>>(ndofs); sweeper->set_quadrature(quad); sweeper->set_factory(factory); sweeper->set_residual_tolerances(abs_residual_tol, rel_residual_tol); sdc.add_level(sweeper); sdc.set_duration(0.0, 4*0.01, 0.01, 4); sdc.set_options(); sdc.setup(); auto q0 = sweeper->get_start_state(); sweeper->exact(q0, 0.0); sdc.run(); fftw_cleanup(); return sweeper->get_errors(); }
int main(void) { double *in, *in2, *out, *out2; fftw_plan p, q; int i, n = 12; in = (double *) fftw_malloc(sizeof(*in) * (n + 1)); in2 = (double *) fftw_malloc(sizeof(*in2) * (n + 1)); out = (double *) fftw_malloc(sizeof(*out) * n); out2 = (double *) fftw_malloc(sizeof(*out2) * n); p = fftw_plan_r2r_1d(n, in + 1, out, FFTW_RODFT01, FFTW_ESTIMATE); /* Note that the frequency is a half integer divided by n */ for (i = 0; i <= n; i++) in[i] = sin(M_PI*(2*3.25)*i/n); fftw_execute(p); sint3(n, in, out2); for (i = 0; i < n; i++) printf("%6d %20.10f | %20.10f\n", i, out[i], out2[i]); printf("\nApplying the inverse transform:\n"); q = fftw_plan_r2r_1d(n, out, in2 + 1, FFTW_RODFT10, FFTW_ESTIMATE); fftw_execute(q); for (i = 0; i < n; i++) printf("%6d %20.10f | %20.10f\n", i, in[i], in2[i]/(2*n)); fftw_destroy_plan(p); fftw_destroy_plan(q); fftw_cleanup(); fftw_free(in); fftw_free(in2); fftw_free(out); fftw_free(out2); return 0; }
int main() { double input[COUNT]; double delta = 0.001; //1ms zwischen samples, willkürlich, printf("sinuswerte:\n"); for(unsigned int i = 0; i < COUNT; i++) { //input[i] = sin((double)2*M_PI*i/10); //alle 20 i eine periode -> delta = 1ms -> T = 20ms -> f = 50Hz input[i] = sin((double)2*M_PI*i/10) + sin((double)2*M_PI*i/2.5); // 50Hz + 200Hz printf("sin(2pi*%d/10) = %f\n",i,input[i]); } double output[COUNT]; for(unsigned int i = 0; i < COUNT; i++) output[i] = 0; fftw_plan plan = fftw_plan_r2r_1d(COUNT,input,output,FFTW_R2HC,FFTW_ESTIMATE); if( plan == 0 ) { printf("plan ist null\n"); return 1; } fftw_execute(plan); printf("ffw-werte:\n"); for(unsigned int i = 0; i < COUNT; i++) { double f = (double)i/COUNT/delta/2; //frequenz berechnen printf( "fft[%d = %fHz] = %f\n", i, f, fabs(output[COUNT-i]*2/COUNT) ); //r2hc fft ist "umgekehrt", betrag anpassen! } fftw_destroy_plan(plan); fftw_cleanup(); return 0; }
Fourier::~Fourier() { const char* fname = "void Fourier::Finalize()"; //---- This is the last instance of Hamiltonian VRB.Debug(fname, "Deallocating memory and destoying plans for FFTW."); #ifdef USE_SINGLE fftwf_free(b); fftwf_destroy_plan(p1); fftwf_destroy_plan(p2); fftwf_cleanup(); #endif #ifdef USE_DOUBLE fftw_free(b); fftw_destroy_plan(p1); fftw_destroy_plan(p2); fftw_cleanup(); #endif #ifdef USE_LONG_DOUBLE fftwl_free(b); fftwl_destroy_plan(p1); fftwl_destroy_plan(p2); fftwl_cleanup(); #endif }
/** * \brief Perform the fourier transform * * This method uses the real-data fourier transform from the FFTW3 library * to compute the fourier transform of the real pixel data. To match the * different conventions how image data is stored, the ny or n1 dimension * of the fftw data array needs to be the width of the image. */ void FourierImage::fourier(const Image<double>& image) { // make sure image has the right dimensions (the ones we stored in // _orig) if (_orig != image.size()) { throw std::range_error("wrong dims for fourier transform"); } // get the dimensions (note the differing data storage conventions // used in fftw3 and in our image class) int n0 = image.size().height(); int n1 = image.size().width(); debug(LOG_DEBUG, DEBUG_LOG, 0, "fourier transform dimensions: %d x %d", n0, n1); // compute the fourier transform fftw_plan p = fftw_plan_dft_r2c_2d(n0, n1, image.pixels, (fftw_complex *)pixels, FFTW_ESTIMATE); fftw_execute(p); fftw_destroy_plan(p); fftw_cleanup(); debug(LOG_DEBUG, DEBUG_LOG, 0, "fourier transform completed"); #if 0 // renormalize double v = 1 / sqrt(n0 *n1); size_t m = size().getPixels(); for (size_t o = 0; o < m; o++) { pixels[o] *= v; } #endif }
int main(void) { double *in, *in2, *out, *out2; fftw_plan p, q; int i, n = 12; in = (double *) fftw_malloc(sizeof(*in) * n); in2 = (double *) fftw_malloc(sizeof(*in2) * n); out = (double *) fftw_malloc(sizeof(*out) * n); out2 = (double *) fftw_malloc(sizeof(*out2) * n); p = fftw_plan_r2r_1d(n, in, out, FFTW_DHT, FFTW_ESTIMATE); // for n = 3: in[0] = 0; in[1] = 1; in[2] = 2; for (i = 0; i < n; i++) in[i] = sin(2*M_PI*3*(i + 0.3)/n); fftw_execute(p); ht(n, in, out2); for (i = 0; i < n; i++) printf("%6d %20.10f | %20.10f\n", i, out[i], out2[i]); printf("\nApplying the inverse transform:\n"); q = fftw_plan_r2r_1d(n, out, in2, FFTW_DHT, FFTW_ESTIMATE); fftw_execute(q); for (i = 0; i < n; i++) printf("%6d %20.10f | %20.10f\n", i, in[i], in2[i]/n); fftw_destroy_plan(p); fftw_destroy_plan(q); fftw_cleanup(); fftw_free(in); fftw_free(in2); fftw_free(out); fftw_free(out2); return 0; }
void fft_destroy() { #ifdef HAVE_LIBFFTW3 fftw_cleanup(); #endif #ifdef HAVE_LIBPTHREAD pthread_mutex_destroy(&mutex); #endif }
/* Free any FFTW resources. */ void fftwDeinit(void) { fftw_destroy_plan(fftw.plan); fftw_free(fftw.in); fftw_free(fftw.out); free(fftw.currentLine); free(fftw.textureData); fftw_cleanup(); }
int main (void) { fftw_complex in[N], out[N], in2[N2], out2[N2]; /* double [2] */ fftw_plan p, q; int i; int half; half=(N/2+1); /* prepare a cosine wave */ for (i = 0; i < N; i++) { //in[i][0] = cos ( 3 * 2 * M_PI * i / N); in[i][0] = (i > 3 && i< 12 )?1:0; in[i][1] = (i > 3 && i< 12 )?1:0; //in[i][1] = 0; } /* forward Fourier transform, save the result in 'out' */ p = fftw_plan_dft_1d (N, in, out, FFTW_FORWARD, FFTW_ESTIMATE); fftw_execute (p); for (i = 0; i < N; i++) printf ("input: %3d %+9.5f %+9.5f I %+9.5f %+9.5f I\n", i, in[i][0], in[i][1],out[i][0],out[i][1]); fftw_destroy_plan (p); for (i = 0; i<N; i++) {out2[i][0]=0.;out2[i][1]=0.;} for (i = 0; i<half; i++) { out2[i][0]=2.*out[i][0]; out2[i][1]=2.*out[i][1]; } for (i = half;i<N;i++) { out2[N+i][0]=2.*out[i][0]; out2[N+i][1]=2.*out[i][1]; } /* backward Fourier transform, save the result in 'in2' */ printf ("\nInverse transform:\n"); q = fftw_plan_dft_1d (N2, out2, in2, FFTW_BACKWARD, FFTW_ESTIMATE); fftw_execute (q); /* normalize */ for (i = 0; i < N2; i++) { in2[i][0] /= N2; in2[i][1] /= N2; } for (i = 0; i < N2; i++) printf ("recover: %3d %+9.1f %+9.1f I\n", i, in2[i][0], in2[i][1]); fftw_destroy_plan (q); fftw_cleanup (); return 0; }
void aubio_cleanup (void) { #ifdef HAVE_FFTW3F fftwf_cleanup (); #else #ifdef HAVE_FFTW3 fftw_cleanup (); #endif #endif }
///Clean up the FFTW code, freeing memory void FFTCleanUp() { FFTManager::Instance()->Clean(); //Clean up fftw #ifdef FFTW_WITH_THREADS fftw_cleanup_threads(); #else fftw_cleanup(); #endif delete FFTManager::Instance(); }
static int circle(bool print) { int angle_updates[ITERATIONS + 1]; build_angle_updates(angle_updates); #define NUM (2048) #define SNUM (NUM / 2 + 1) double var = 0; double mean = 0; static double errors[NUM]; static complex spectrum[SNUM]; fftw_plan plan = fftw_plan_dft_r2c_1d(NUM, errors, spectrum, 0); for (int i = 0; i != NUM; ++i) { double angle = (i + drand48()) * (2 * M_PI / NUM); assert (0 < angle && angle < 2 * M_PI); word_t qq = CMASK((long) floor(cos(angle) * (1l << 32))); word_t ii = CMASK((long) floor(sin(angle) * (1l << 32))); double err = terror(qq, ii, angle_updates); errors[i] = err; var += err * err; mean += err; if (print) printf("%5i % .2f\n", i, err); } mean /= NUM; var = var / NUM - mean * mean; fprintf(stderr, "Mean = %f, var = %f, std. dev. = %f\n", mean, var, sqrt(var)); //fftw_execute_dft_r2c(plan, errors, spectrum); fftw_execute(plan); static enum_double power[SNUM]; for (int i = 1; i != SNUM; ++i) power[i] = (enum_double) { i, cnorm(spectrum[i]) }; qsort(power, SNUM - 1, sizeof(enum_double), compare_enum_double); fprintf(stderr, "Harmonic Amplitude Real Imaginary\n"); for (int i = 0; i != 10; ++i) { int index = power[i].index; fprintf(stderr, " %7i %8.4f%% % f % f\n", index, sqrt(power[i].value) * (100.0 / NUM), creal(spectrum[index]), cimag(spectrum[index])); } fftw_destroy_plan(plan); fftw_cleanup(); return 0; }
/* gcc 1dc1min.c -lfftw3 */ #include <stdio.h> #include <math.h> #include <fftw3.h> #define n (128+1) /* notice the "+1" */ int main(void) { double in[n], in2[n], out[n]; fftw_plan p, q; int i; p = fftw_plan_r2r_1d(n, in, out, FFTW_REDFT00, FFTW_ESTIMATE); for (i = 0; i < n; i++) in[i] = cos(2*M_PI*10*i/(n - 1)); /* n - 1 instead of n */ fftw_execute(p); q = fftw_plan_r2r_1d(n, out, in2, FFTW_REDFT00, FFTW_ESTIMATE); fftw_execute(q); for (i = 0; i < n; i++) printf("%3d %9.5f %9.5f\n", i, in[i], in2[i]/(2*(n - 1))); /* n - 1 instead of n */ fftw_destroy_plan(p); fftw_destroy_plan(q); fftw_cleanup(); return 0; }
void reinit_extace(int new_nsamp) { /* Stop drawing the display */ draw_stop(); if(data_handle != -1) /* stop if previously opened */ { input_thread_stopper(data_handle); close_datasource(data_handle); } /* Free all buffers */ mem_dealloc(); scope_begin_l = 0; scope_begin_l = 0; /* auto shift lag slightly to maintain good sync * The idea is the shift the lag slighly so that the "on-time" data * is in the MIDDLE of the window function for better eye/ear matchup */ nsamp = new_nsamp; convolve_factor = floor(nsamp/width) < 3 ? floor(nsamp/width) : 3 ; if (convolve_factor == 0) convolve_factor = 1; recalc_markers = TRUE; recalc_scale = TRUE; mem_alloc(); setup_datawindow(NULL,(WindowFunction)window_func); ring_rate_changed(); ring_pos=0; /* only start if it has been stopped above */ if(data_handle != -1 && (data_handle=open_datasource(data_source)) >= 0) { #ifdef USING_FFTW2 fftw_destroy_plan(plan); plan = fftw_create_plan(nsamp, FFTW_FORWARD, FFTW_ESTIMATE); #elif USING_FFTW3 fftw_cleanup(); plan = fftw_plan_r2r_1d(nsamp, raw_fft_in, raw_fft_out,FFTW_R2HC, FFTW_ESTIMATE); #endif input_thread_starter(data_handle); ring_rate_changed(); /* Fix all gui controls that depend on * ring_rate (adjustments and such */ draw_start(); } }
/****** fft_end ************************************************************ PROTO void fft_init(void) PURPOSE Clear up stuff set by FFT routines INPUT -. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 29/11/2006 ***/ void fft_end(void) { if (firsttimeflag) { firsttimeflag = 0; #ifdef USE_THREADS fftw_cleanup_threads(); QPTHREAD_MUTEX_DESTROY(&fftmutex); #endif fftw_cleanup(); } return; }
Correlation::~Correlation() { fftw_destroy_plan(m_planA); fftw_destroy_plan(m_planB); fftw_destroy_plan(m_planX); fftw_free(m_signalA); fftw_free(m_signalB); fftw_free(m_outShifted); fftw_free(m_out); fftw_free(m_outA); fftw_free(m_outB); fftw_cleanup(); }
/** * Compares accuracy of the fast Gauss transform with increasing expansion * degree. * * \author Stefan Kunis */ void fgt_test_error(void) { fgt_plan my_plan; double _Complex *swap_dgt; int n,mi; double _Complex sigma=4*(138+ _Complex_I*100); int N=1000; int M=1000; int m[2]={7,3}; printf("N=%d;\tM=%d;\nsigma=%1.3e+i*%1.3e;\n",N,M,creal(sigma),cimag(sigma)); printf("error=[\n"); swap_dgt = (double _Complex*)nfft_malloc(M*sizeof(double _Complex)); for(n=8; n<=128; n+=4) { printf("%d\t",n); for(mi=0;mi<2;mi++) { fgt_init_guru(&my_plan, N, M, sigma, n, 1, m[mi], 0); fgt_test_init_rand(&my_plan); fgt_init_node_dependent(&my_plan); NFFT_SWAP_complex(swap_dgt,my_plan.f); dgt_trafo(&my_plan); NFFT_SWAP_complex(swap_dgt,my_plan.f); fgt_trafo(&my_plan); printf("%1.3e\t", X(error_l_infty_1_complex)(swap_dgt, my_plan.f, my_plan.M, my_plan.alpha, my_plan.N)); fflush(stdout); fgt_finalize(&my_plan); fftw_cleanup(); } printf("\n"); } printf("];\n"); nfft_free(swap_dgt); }
void sinefft(struct poisson* thePoisson){ int i,j,k; double *in=thePoisson->density; const int N_element=thePoisson->N_z_glob; int N_k=thePoisson->N_k; int N_r_glob=thePoisson->N_r_glob; int N_z_glob=thePoisson->N_z_glob; const double uni=sqrt(0.5*(N_element+1)); /* double * sine_buf=thePoisson->shortbuffer; fftw_plan p; for(j=0;j<N_k;j++) for(i=0;i<N_r_glob;i++){ for(k=0;k<N_z_glob;k++) sine_buf[k]=in[in_lookup(thePoisson,k,i,j)]; p=fftw_plan_r2r_1d(N_element, sine_buf,sine_buf,FFTW_RODFT00,FFTW_ESTIMATE); fftw_execute(p); for(k=0;k<N_z_glob;k++) in[in_lookup(thePoisson,k,i,j)]=sine_buf[k]/2.0/uni; fftw_destroy_plan(p); } */ double * sine_buf=thePoisson->buffer; int idx=0; for(j=0;j<N_k;j++) for(i=0;i<N_r_glob;i++) for(k=0;k<N_z_glob;k++) sine_buf[idx++]=in[in_lookup(thePoisson,k,i,j)]; const int n[1]={N_element}; const fftw_r2r_kind kind[1]={FFTW_RODFT00}; fftw_plan p=fftw_plan_many_r2r(1,n,N_k*N_r_glob,sine_buf,n,1,N_element,sine_buf,n,1,N_element,kind,FFTW_ESTIMATE); fftw_execute(p); fftw_destroy_plan(p); idx=0; i=0;j=0;k=0; for(j=0;j<N_k;j++) for(i=0;i<N_z_glob;i++) for(k=0;k<N_z_glob;k++) in[in_lookup(thePoisson,k,i,j)]=sine_buf[idx++]/2.0/uni; fftw_cleanup(); //nnote: in and out should have the same size;same size after sine transform }
void cleanup( Search_settings *sett, Command_line_opts *opts, Search_range *s_range, FFTW_plans *plans, FFTW_arrays *fftw_arr, Aux_arrays *aux, double *F) { int i; for(i=0; i<sett->nifo; i++) { free(ifo[i].sig.xDat); free(ifo[i].sig.xDatma); free(ifo[i].sig.xDatmb); free(ifo[i].sig.DetSSB); free(ifo[i].sig.aa); free(ifo[i].sig.bb); free(ifo[i].sig.shftf); free(ifo[i].sig.shft); } free(aux->sinmodf); free(aux->cosmodf); free(aux->t2); free(F); fftw_free(fftw_arr->xa); free(sett->M); fftw_destroy_plan(plans->plan); fftw_destroy_plan(plans->plan2); fftw_destroy_plan(plans->pl_int); fftw_destroy_plan(plans->pl_int2); fftw_destroy_plan(plans->pl_inv); fftw_destroy_plan(plans->pl_inv2); fftw_forget_wisdom(); fftw_cleanup(); } // end of cleanup & memory free
void FourierTransformer::cleanup() { // First clear object and destroy plans clear(); // Then clean up all the junk fftw keeps lying around // SOMEHOW THE FOLLOWING IS NOT ALLOWED WHEN USING MULTPLE TRANSFORMER OBJECTS.... if (threadsSetOn) { fftw_cleanup_threads(); } else { fftw_cleanup(); } #ifdef DEBUG_PLANS std::cerr << "CLEANED-UP this= " << this << std::endl; #endif }
/*! this is a straight forward main function, that does the following - load lua config file - get configuration table from config - contruct a preferences class from them - start simulation according to the preferences - dump the result as precified in preferences */ int main(int argc, char * argv[argc]) { fftw_init_threads(); fftw_plan_with_nthreads(4); if (argc != 3) { fprintf(stderr, "usage: %s config.lua result.dat\n", argv[0]); return -1; } lua_State * L = luaL_newstate(); luaL_openlibs(L); preferences_t * prefs = preferences_new(); if (luaL_dofile(L, argv[1])) { fprintf(stderr, "could not load '%s' : %s\n", argv[1], lua_tostring(L, 1)); } else { // get config table lua_getfield(L, LUA_GLOBALSINDEX, "config"); if (lua_isnil(L, -1)) { fprintf(stderr, "table config undefined\n"); } else { // ref config table, so we can access it in preferences_read() prefs->config = luaL_ref(L, LUA_REGISTRYINDEX); if (!preferences_read(L, prefs)) { if (!start_simulation(prefs)) { FILE * fp = fopen(argv[2], "wb"); assert(fp); dump_results(prefs, fp); fclose(fp); } } } } preferences_free(prefs); lua_close(L); fftw_cleanup(); fftw_cleanup_threads(); pthread_exit(NULL); }
/** * Compares accuracy of the fast Gauss transform with increasing expansion * degree and different periodisation lengths. * * \author Stefan Kunis */ void fgt_test_error_p(void) { fgt_plan my_plan; double _Complex *swap_dgt; int n,pi; double _Complex sigma=20+40*_Complex_I; int N=1000; int M=1000; double p[3]={1,1.5,2}; printf("N=%d;\tM=%d;\nsigma=%1.3e+i*%1.3e;\n",N,M,creal(sigma),cimag(sigma)); printf("error=[\n"); swap_dgt = (double _Complex*)nfft_malloc(M*sizeof(double _Complex)); for(n=8; n<=128; n+=4) { printf("%d\t",n); for(pi=0;pi<3;pi++) { fgt_init_guru(&my_plan, N, M, sigma, n, p[pi], 7, 0); fgt_test_init_rand(&my_plan); fgt_init_node_dependent(&my_plan); NFFT_SWAP_complex(swap_dgt,my_plan.f); dgt_trafo(&my_plan); NFFT_SWAP_complex(swap_dgt,my_plan.f); fgt_trafo(&my_plan); printf("%1.3e\t", X(error_l_infty_1_complex)(swap_dgt, my_plan.f, my_plan.M, my_plan.alpha, my_plan.N)); fflush(stdout); fgt_finalize(&my_plan); fftw_cleanup(); } printf("\n"); } printf("];\n"); }
/** * \brief Compute the inverse transform * * Note that in order to get inverse, we also have to divide by the volume * of the domain, which explains why we do all this only for float valued * pixels. */ ImagePtr FourierImage::inverse() const { Image<double> *image = new Image<double>(_orig); int n0 = _orig.height(); int n1 = _orig.width(); debug(LOG_DEBUG, DEBUG_LOG, 0, "inverse transform, (%d,%d)", n0, n1); // compute the fourier transform fftw_plan p = fftw_plan_dft_c2r_2d(n0, n1, (fftw_complex *)pixels, image->pixels, FFTW_ESTIMATE); fftw_execute(p); fftw_destroy_plan(p); fftw_cleanup(); debug(LOG_DEBUG, DEBUG_LOG, 0, "inverse fourier transform complete"); // normalize to the dimensions of the domain double value = 1. / (n0 * n1); int w = _orig.width(); int h = _orig.height(); for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { image->pixel(x, y) = image->pixel(x, y) * value; } } return ImagePtr(image); }
int main( int argc, char* argv[]) { //Parameter initialisation std::vector<double> para; if( argc == 1) { std::cout << "Reading from input.txt\n"; try{ para = file::read_input( "input.txt"); } catch (toefl::Message& m) { m.display(); throw m; } } else if( argc == 2) { std::cout << "Reading from "<<argv[1]<<"\n"; try{ para = file::read_input( argv[1]); } catch (toefl::Message& m) { m.display(); throw m; } } else { std::cerr << "ERROR: Too many arguments!\nUsage: "<< argv[0]<<" [filename]\n"; return -1; } omp_set_num_threads( para[20]); std::cout<< "With "<<omp_get_max_threads()<<" threads\n"; const toefl::Parameters p(para); field_ratio = p.lx/p.ly; if( p.bc_x != toefl::TL_PERIODIC) { std::cerr << "Only periodic boundaries allowed!\n"; return -1; } try{p.consistencyCheck();} catch( toefl::Message& m){m.display();throw m;} p.display(std::cout); //construct solvers toefl::DFT_DFT_Solver<3> solver( p); // place some gaussian blobs in the field try{ toefl::Matrix<double, toefl::TL_DFT> ne{ p.ny, p.nx, 0.}, nz{ ne}, phi{ ne}; init_gaussian( ne, p.posX, p.posY, p.blob_width/p.lx, p.blob_width/p.ly, p.amp); //init_gaussian_column( nz, 0.6, 0.05/field_ratio, p.imp_amp); std::array< toefl::Matrix<double, toefl::TL_DFT>,3> arr3{{ ne, nz, phi}}; //now set the field to be computed solver.init( arr3, toefl::IONS); }catch( toefl::Message& m){m.display();} cv::VideoCapture cap(0); if( !cap.isOpened()) { std::cerr << "Camera not found\n"; return -1; } cap.set( CV_CAP_PROP_FRAME_WIDTH, p.nx); cap.set( CV_CAP_PROP_FRAME_HEIGHT, p.ny); cv::Mat last, current, flow, vel(p.ny, p.nx, CV_32F); std::vector<cv::Mat> v; cv::namedWindow("Current",cv::WINDOW_NORMAL); cv::namedWindow("Velocity",cv::WINDOW_NORMAL); double t = 0.; toefl::Timer timer; toefl::Timer overhead; solver.first_step(); solver.second_step(); t+= 2*p.dt; toefl::Matrix<double, toefl::TL_DFT> src( p.ny, p.nx, 0.); cv::Mat grey, colored, show( p.ny, p.nx, CV_32F); cap >> last; cv::cvtColor( last, last, CV_BGR2GRAY); //convert colors while( true) { init_gaussian( src, 0.5+0.25*sin(t), 0.75, p.blob_width/p.lx, p.blob_width/p.ly, p.amp); cap >> current; // get a new frame from camera cv::cvtColor(current, current, CV_BGR2GRAY); //convert colors cv::GaussianBlur(current, current, cv::Size(21,21), 0, 0); //Kernel size, sigma_x, sigma_y calcOpticalFlowFarneback(last, current, flow, 0.5, 1, 5, 3, 5, 1.2, 0); cv::split( flow, v); //erster index y, zweiter index x for( unsigned i=0; i<v[0].rows; i++) for( unsigned j=0; j<v[0].cols; j++) vel.at<float>( i,j) = sqrt( v[0].at<float>(i,j)*v[0].at<float>(i,j) + v[1].at<float>(i,j)*v[1].at<float>(i,j) ); for( unsigned i=0; i<vel.rows; i++) for( unsigned j=0; j<vel.cols; j++) if( vel.at<float>(i,j) < 1) vel.at<float>(i,j) = 0; //scale velocity to 1 in order to account for distance from camera double min, max; cv::minMaxLoc( vel, &min, &max); std::cout << min <<" "<<max<<std::endl; if( max > 1) // if someone is there for( unsigned i=0; i<vel.rows; i++) for( unsigned j=0; j<vel.cols; j++) vel.at<float>( i,j) /= max; cv::flip( vel, vel, +1); //for( unsigned i=0; i<src.rows(); i++) // for( unsigned j=0; j<src.cols(); j++) // src(i,j) = 0.5*vel.at<double>(i,j); overhead.tic(); //const toefl::Matrix<double, toefl::TL_DFT>& field = solver.getField( toefl::IMPURITIES); const toefl::Matrix<double, toefl::TL_DFT>& field = solver.getField( toefl::ELECTRONS); for( unsigned i=0; i<p.ny; i++) for( unsigned j=0; j<p.nx; j++) show.at<float>(i,j) = (float)field(i,j); cv::minMaxLoc( show, &min, &max); show.convertTo(grey, CV_8U, 255.0/(2.*max), 255.0/2.); cv::minMaxLoc( grey, &min, &max); //cv::applyColorMap( grey, colored, cv::COLORMAP_BONE); //cv::applyColorMap( grey, colored, cv::COLORMAP_COOL); //cv::applyColorMap( grey, colored, cv::COLORMAP_HOT); //cv::applyColorMap( grey, colored, cv::COLORMAP_HSV); //cv::applyColorMap( grey, colored, cv::COLORMAP_JET); cv::applyColorMap( grey, colored, cv::COLORMAP_OCEAN); //cv::applyColorMap( grey, colored, cv::COLORMAP_PINK); //cv::applyColorMap( grey, colored, cv::COLORMAP_RAINBOW); //cv::applyColorMap( grey, colored, cv::COLORMAP_SPRING); //cv::applyColorMap( grey, colored, cv::COLORMAP_SUMMER); //cv::applyColorMap( grey, colored, cv::COLORMAP_AUTUMN); //cv::applyColorMap( grey, colored, cv::COLORMAP_WINTER); window_str << std::setprecision(2) << std::fixed; window_str << "time = "<<t; //cv::addText( colored, window_str.str(), cv::Point(50,50)); window_str.str(""); std::cout << colored.rows << " " << colored.cols<<"\n"; std::cout << vel.rows << " " << vel.cols<<"\n"; std::cout << show.rows << " " << show.cols<<"\n"; std::cout << src.rows() << " " << src.cols()<<"\n"; cv::imshow("Current", colored); //for( unsigned i=0; i<src.rows(); i++) //for( unsigned j=0; j<src.cols(); j++) //show.at<double>(i,j) = src(i,j); cv::imshow("Velocity", vel); timer.tic(); for(unsigned i=0; i<p.itstp; i++) { toefl::Matrix<double, toefl::TL_DFT> voidmatrix( 2,2,(bool)toefl::TL_VOID); solver.step(src ); t+= p.dt; } timer.toc(); overhead.toc(); //swap fields cv::Mat temp = last; last = current; current = temp; if(cv::waitKey(30) >= 0) break; } ////////////////////////////////glfw and opencv////////////////////////////// std::cout << "Average time for one step = "<<timer.diff()/(double)p.itstp<<"s\n"; std::cout << "Overhead for visualisation, etc. per step = "<<(overhead.diff()-timer.diff())/(double)p.itstp<<"s\n"; ////////////////////////////////////////////////////////////////// fftw_cleanup(); return 0; }
//TODO: nest in channel for multi-channel plot int writeFFT(int N, struct WaveHeader *wav){ int i, j; double *in; double mag = 0.0; double freqBin = 0.0; double correction = 0.0; fftw_complex * out; fftw_plan my_plan; FILE * fDatOut; int nameLength = 0; char datFilename[300]; //add ".dat" to the end of the file //will fix later to rename ".wav" nameLength = sizeof(wav->wavName)/sizeof(wav->wavName[0]); snprintf(datFilename, nameLength+4, "%s.dat", wav->wavName); fDatOut = fopen(datFilename, "w"); //Not sure how to test this one if (!fDatOut) { fprintf(stderr,"\n**ERROR opening dat file for writing!**\n"); return 1; } correction = (double)wav->sampleRate / (double)N; in = (double*) fftw_malloc(sizeof(double)*N); out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*((N/2)+1)); my_plan = fftw_plan_dft_r2c_1d(N, in, out, FFTW_MEASURE); printf("Calcuting FFT, placing dat file at \'%s\'\n",datFilename); //Iterate through the entire wav file, overlap & add by buffer size for (i = 0; i < wav->totalSamples; i=i+(N-N/2)) { //Iterate through the sample size for (j = 0; j < N; j++) { if ((i+j) < wav->totalSamples) { in[j] = wav->chan1[(i+j)]*(0.54 - 0.46 * cos(2 * M_PI * j / (N-1))); } } //Perform FFT for the sample size fftw_execute(my_plan); //Iterate through sample size //skip the first element, since it is the average of the sample for (j = 1; j<(N/2)+1; j++) { mag = 2*(out[j][0]*out[j][0] + out[j][1]*out[j][1])/N; //Set the frequency bin freqBin = (double)(j) * correction; //Print out (sample FreqBin dB (unscaled)) //This can be used with gnuplot or matlab to generate spectrogram fprintf(fDatOut,"%d %f %f \n",i,freqBin,(10. * log10(mag+0.001))/log10(10)); } //gnuplot requires a line break between sample sets for spectrograms fprintf(fDatOut,"\n"); } fftw_free(in); fftw_free(out); fftw_destroy_plan(my_plan); fftw_cleanup(); fclose(fDatOut); //write gnuplot script printf("Writing spec.gp\n"); writeGpScript(datFilename,wav->sampleRate, N); return 0; }
void smurf_sc2fft( int *status ) { int avpspec=0; /* Flag for doing average power spectrum */ double avpspecthresh=0; /* Threshold noise for detectors in avpspec */ Grp * basegrp = NULL; /* Basis group for output filenames */ smfArray *bbms = NULL; /* Bad bolometer masks */ smfArray *concat=NULL; /* Pointer to a smfArray */ size_t contchunk; /* Continuous chunk counter */ smfArray *darks = NULL; /* dark frames */ int ensureflat; /* Flag for flatfielding data */ Grp *fgrp = NULL; /* Filtered group, no darks */ smfArray *flatramps = NULL;/* Flatfield ramps */ AstKeyMap *heateffmap = NULL; /* Heater efficiency data */ size_t gcount=0; /* Grp index counter */ size_t i; /* Loop counter */ smfGroup *igroup=NULL; /* smfGroup corresponding to igrp */ Grp *igrp = NULL; /* Input group of files */ int inverse=0; /* If set perform inverse transform */ int isfft=0; /* Are data fft or real space? */ dim_t maxconcat=0; /* Longest continuous chunk length in samples */ size_t ncontchunks=0; /* Number continuous chunks outside iter loop */ smfData *odata=NULL; /* Pointer to output smfData to be exported */ Grp *ogrp = NULL; /* Output group of files */ size_t outsize; /* Total number of NDF names in the output group */ int polar=0; /* Flag for FFT in polar coordinates */ int power=0; /* Flag for squaring amplitude coeffs */ size_t size; /* Number of files in input group */ smfData *tempdata=NULL; /* Temporary smfData pointer */ int weightavpspec=0; /* Flag for 1/noise^2 weighting */ ThrWorkForce *wf = NULL; /* Pointer to a pool of worker threads */ int zerobad; /* Zero VAL__BADD before taking FFT? */ /* Main routine */ ndfBegin(); /* Find the number of cores/processors available and create a pool of threads of the same size. */ wf = thrGetWorkforce( thrGetNThread( SMF__THREADS, status ), status ); /* Get input file(s) */ kpg1Rgndf( "IN", 0, 1, "", &igrp, &size, status ); /* Filter out darks */ smf_find_science( igrp, &fgrp, 1, NULL, NULL, 1, 1, SMF__NULL, &darks, &flatramps, &heateffmap, NULL, status ); /* input group is now the filtered group so we can use that and free the old input group */ size = grpGrpsz( fgrp, status ); grpDelet( &igrp, status); igrp = fgrp; fgrp = NULL; /* We now need to combine files from the same subarray and same sequence to form a continuous time series */ smf_grp_related( igrp, size, 1, 0, 0, NULL, NULL, &maxconcat, NULL, &igroup, &basegrp, NULL, status ); /* Get output file(s) */ size = grpGrpsz( basegrp, status ); if( size > 0 ) { kpg1Wgndf( "OUT", basegrp, size, size, "More output files required...", &ogrp, &outsize, status ); } else { msgOutif(MSG__NORM, " ", TASK_NAME ": All supplied input frames were DARK," " nothing to do", status ); } /* Get group of bolometer masks and read them into a smfArray */ smf_request_mask( "BBM", &bbms, status ); /* Obtain the number of continuous chunks and subarrays */ if( *status == SAI__OK ) { ncontchunks = igroup->chunk[igroup->ngroups-1]+1; } msgOutiff( MSG__NORM, "", "Found %zu continuous chunk%s", status, ncontchunks, (ncontchunks > 1 ? "s" : "") ); /* Are we flatfielding? */ parGet0l( "FLAT", &ensureflat, status ); /* Are we doing an inverse transform? */ parGet0l( "INVERSE", &inverse, status ); /* Are we using polar coordinates instead of cartesian for the FFT? */ parGet0l( "POLAR", &polar, status ); /* Are we going to assume amplitudes are squared? */ parGet0l( "POWER", &power, status ); /* Are we going to zero bad values first? */ parGet0l( "ZEROBAD", &zerobad, status ); /* Are we calculating the average power spectrum? */ parGet0l( "AVPSPEC", &avpspec, status ); if( avpspec ) { power = 1; parGet0d( "AVPSPECTHRESH", &avpspecthresh, status ); parGet0l( "WEIGHTAVPSPEC", &weightavpspec, status ); } /* If power is true, we must be in polar form */ if( power && !polar) { msgOutif( MSG__NORM, " ", TASK_NAME ": power spectrum requested so setting POLAR=TRUE", status ); polar = 1; } gcount = 1; for( contchunk=0;(*status==SAI__OK)&&contchunk<ncontchunks; contchunk++ ) { size_t idx; /* Concatenate this continuous chunk but forcing a raw data read. We will need quality. */ smf_concat_smfGroup( wf, NULL, igroup, darks, NULL, flatramps, heateffmap, contchunk, ensureflat, 1, NULL, 0, NULL, NULL, 0, 0, 0, &concat, NULL, status ); /* Now loop over each subarray */ /* Export concatenated data for each subarray to NDF file */ for( idx=0; (*status==SAI__OK)&&idx<concat->ndat; idx++ ) { if( concat->sdata[idx] ) { smfData * idata = concat->sdata[idx]; int provid = NDF__NOID; dim_t nbolo; /* Number of detectors */ dim_t ndata; /* Number of data points */ /* Apply a mask to the quality array and data array */ smf_apply_mask( idata, bbms, SMF__BBM_QUAL|SMF__BBM_DATA, 0, status ); smf_get_dims( idata, NULL, NULL, &nbolo, NULL, &ndata, NULL, NULL, status ); /* Check for double precision data */ if( idata->dtype != SMF__DOUBLE ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": data are not double precision.", status ); } /* Are we zeroing VAL__BADD? */ if( (*status==SAI__OK) && zerobad ) { double *data= (double *) idata->pntr[0]; for( i=0; i<ndata; i++ ) { if( data[i] == VAL__BADD ) { data[i] = 0; } } } /* Check whether we need to transform the data at all */ isfft = smf_isfft(idata,NULL,NULL,NULL,NULL,NULL,status); if( isfft && avpspec && (*status == SAI__OK) ) { *status = SAI__ERROR; errRep( "", FUNC_NAME ": to calculate average power spectrum input data cannot " "be FFT", status ); } if( (*status == SAI__OK) && (isfft == inverse) ) { if( avpspec ) { /* If calculating average power spectrum do the transforms with smf_bolonoise so that we can also measure the noise of each detector */ double *whitenoise=NULL; smf_qual_t *bolomask=NULL; double mean, sig, freqlo; size_t ngood, newgood; whitenoise = astCalloc( nbolo, sizeof(*whitenoise) ); bolomask = astCalloc( nbolo, sizeof(*bolomask) ); freqlo = 1. / (idata->hdr->steptime * idata->hdr->nframes); smf_bolonoise( wf, idata, 1, freqlo, SMF__F_WHITELO, SMF__F_WHITEHI, 1, 0, whitenoise, NULL, &odata, status ); /* Initialize quality */ for( i=0; i<nbolo; i++ ) { if( whitenoise[i] == VAL__BADD ) { bolomask[i] = SMF__Q_BADB; } else { /* smf_bolonoise returns a variance, so take sqrt */ whitenoise[i] = sqrt(whitenoise[i]); } } ngood=-1; newgood=0; /* Iteratively cut n-sigma noisy outlier detectors */ while( ngood != newgood ) { ngood = newgood; smf_stats1D( whitenoise, 1, nbolo, bolomask, 1, SMF__Q_BADB, &mean, &sig, NULL, NULL, status ); msgOutiff( MSG__DEBUG, "", TASK_NAME ": mean=%lf sig=%lf ngood=%li\n", status, mean, sig, ngood); newgood=0; for( i=0; i<nbolo; i++ ) { if( whitenoise[i] != VAL__BADD ){ if( (whitenoise[i] - mean) > avpspecthresh *sig ) { whitenoise[i] = VAL__BADD; bolomask[i] = SMF__Q_BADB; } else { newgood++; } } } } msgOutf( "", TASK_NAME ": Calculating average power spectrum of best %li " " bolometers.", status, newgood); /* If using 1/noise^2 weights, calculate 1/whitenoise^2 in-place to avoid allocating another array */ if( weightavpspec ) { msgOutif( MSG__VERB, "", TASK_NAME ": using 1/noise^2 weights", status ); for( i=0; i<nbolo; i++ ) { if( whitenoise[i] && (whitenoise[i] != VAL__BADD) ) { whitenoise[i] = 1/(whitenoise[i]*whitenoise[i]); } } } /* Calculate the average power spectrum of good detectors */ tempdata = smf_fft_avpspec( odata, bolomask, 1, SMF__Q_BADB, weightavpspec ? whitenoise : NULL, status ); smf_close_file( &odata, status ); whitenoise = astFree( whitenoise ); bolomask = astFree( bolomask ); odata = tempdata; tempdata = NULL; /* Store the number of good bolometers */ parPut0i( "NGOOD", newgood, status ); } else { /* Otherwise do forward/inverse transforms here as needed */ /* If inverse transform convert to cartesian representation first */ if( inverse && polar ) { smf_fft_cart2pol( wf, idata, 1, power, status ); } /* Tranform the data */ odata = smf_fft_data( wf, idata, NULL, inverse, 0, status ); smf_convert_bad( wf, odata, status ); if( inverse ) { /* If output is time-domain, ensure that it is ICD bolo-ordered */ smf_dataOrder( odata, 1, status ); } else if( polar ) { /* Store FFT of data in polar form */ smf_fft_cart2pol( wf, odata, 0, power, status ); } } /* open a reference input file for provenance propagation */ ndgNdfas( basegrp, gcount, "READ", &provid, status ); /* Export the data to a new file */ smf_write_smfData( odata, NULL, NULL, ogrp, gcount, provid, MSG__VERB, 0, status ); /* Free resources */ ndfAnnul( &provid, status ); smf_close_file( &odata, status ); } else { msgOutif( MSG__NORM, " ", "Data are already transformed. No output will be produced", status ); } } /* Update index into group */ gcount++; } /* Close the smfArray */ smf_close_related( &concat, status ); } /* Write out the list of output NDF names, annulling the error if a null parameter value is supplied. */ if( *status == SAI__OK ) { grpList( "OUTFILES", 0, 0, NULL, ogrp, status ); if( *status == PAR__NULL ) errAnnul( status ); } /* Tidy up after ourselves: release the resources used by the grp routines */ grpDelet( &igrp, status); grpDelet( &ogrp, status); if (basegrp) grpDelet( &basegrp, status ); if( igroup ) smf_close_smfGroup( &igroup, status ); if( flatramps ) smf_close_related( &flatramps, status ); if (heateffmap) heateffmap = smf_free_effmap( heateffmap, status ); if (bbms) smf_close_related( &bbms, status ); ndfEnd( status ); /* Ensure that FFTW doesn't have any used memory kicking around */ fftw_cleanup(); }
void smurf_sc2clean( int *status ) { smfArray *array = NULL; /* Data to be cleaned */ Grp *basegrp=NULL; /* Grp containing first file each chunk */ size_t basesize; /* Number of files in base group */ smfArray *bbms = NULL; /* Bad bolometer masks */ smfArray *concat=NULL; /* Pointer to a smfArray */ size_t contchunk; /* Continuous chunk counter */ smfArray *darks = NULL; /* Dark data */ int ensureflat; /* Flag for flatfielding data */ smfArray *flatramps = NULL;/* Flatfield ramps */ AstKeyMap *heateffmap = NULL; /* Heater efficiency data */ smfData *odata = NULL; /* Pointer to output data struct */ Grp *fgrp = NULL; /* Filtered group, no darks */ size_t gcount=0; /* Grp index counter */ size_t idx; /* Subarray counter */ Grp *igrp = NULL; /* Input group of files */ smfGroup *igroup=NULL; /* smfGroup corresponding to igrp */ dim_t maxconcat=0; /* Longest continuous chunk length in samples */ double maxlen=0; /* Constrain maxconcat to this many seconds */ size_t ncontchunks=0; /* Number continuous chunks outside iter loop */ Grp *ogrp = NULL; /* Output group of files */ size_t osize; /* Total number of NDF names in the output group */ dim_t padStart=0; /* How many samples padding at start */ dim_t padEnd=0; /* How many samples padding at end */ size_t size; /* Number of files in input group */ int temp; /* Temporary signed integer */ int usedarks; /* flag for using darks */ ThrWorkForce *wf = NULL; /* Pointer to a pool of worker threads */ int writecom; /* Write COMmon mode to NDF if calculated? */ int writegai; /* Write GAIns to NDF if calculated? */ /* Main routine */ ndfBegin(); /* Find the number of cores/processors available and create a pool of threads of the same size. */ wf = thrGetWorkforce( thrGetNThread( SMF__THREADS, status ), status ); /* Read the input file */ kpg1Rgndf( "IN", 0, 1, "", &igrp, &size, status ); /* Filter out darks */ smf_find_science( wf, igrp, &fgrp, 1, NULL, NULL, 1, 1, SMF__NULL, &darks, &flatramps, &heateffmap, NULL, status ); /* input group is now the filtered group so we can use that and free the old input group */ size = grpGrpsz( fgrp, status ); grpDelet( &igrp, status); igrp = fgrp; fgrp = NULL; if (size == 0) { msgOutif(MSG__NORM, " ","All supplied input frames were filtered," " nothing to do", status ); goto CLEANUP; } /* --- Parse ADAM parameters ---------------------------------------------- */ /* Maximum length of a continuous chunk */ parGdr0d( "MAXLEN", 0, 0, VAL__MAXD, 1, &maxlen, status ); /* Padding */ parGdr0i( "PADSTART", 0, 0, VAL__MAXI, 1, &temp, status ); padStart = (dim_t) temp; parGdr0i( "PADEND", 0, 0, VAL__MAXI, 1, &temp, status ); padEnd = (dim_t) temp; /* Are we using darks? */ parGet0l( "USEDARKS", &usedarks, status ); /* Are we flatfielding? */ parGet0l( "FLAT", &ensureflat, status ); /* Write COM/GAI to NDFs if calculated? */ parGet0l( "COM", &writecom, status ); parGet0l( "GAI", &writegai, status ); /* Get group of bolometer masks and read them into a smfArray */ smf_request_mask( wf, "BBM", &bbms, status ); /* Group the input files by subarray and continuity ----------------------- */ smf_grp_related( igrp, size, 1, 0, maxlen-padStart-padEnd, NULL, NULL, &maxconcat, NULL, &igroup, &basegrp, NULL, status ); /* Obtain the number of continuous chunks and subarrays */ if( *status == SAI__OK ) { ncontchunks = igroup->chunk[igroup->ngroups-1]+1; } basesize = grpGrpsz( basegrp, status ); /* Get output file(s) */ kpg1Wgndf( "OUT", basegrp, basesize, basesize, "More output files required...", &ogrp, &osize, status ); /* Loop over continuous chunks and clean -----------------------------------*/ gcount = 1; for( contchunk=0;(*status==SAI__OK)&&contchunk<ncontchunks; contchunk++ ) { AstKeyMap *keymap=NULL; int dkclean; AstKeyMap *sub_instruments=NULL; /* Place cleaning parameters into a keymap and set defaults. Do this inside the loop in case we are cleaning files with differing sub-instruments. Note that we use the map-maker defaults file here (which loads the sc2clean defaults) so that we populate the locked keymap with all the parameters that people may come across to allow them to load their map-maker config directly into sc2clean. */ sub_instruments = smf_subinst_keymap( SMF__SUBINST_NONE, NULL, igrp, igroup->subgroups[contchunk][0], status ); keymap = kpg1Config( "CONFIG", "$SMURF_DIR/smurf_makemap.def", sub_instruments, 1, status ); if( sub_instruments ) sub_instruments = astAnnul( sub_instruments ); /* Now rerun smf_grp_related to figure out how long each downsampled chunk of data will be. */ if( basegrp ) grpDelet( &basegrp, status ); if( igroup ) smf_close_smfGroup( &igroup, status ); smf_grp_related( igrp, size, 1, 0, maxlen-padStart-padEnd, NULL, keymap, &maxconcat, NULL, &igroup, &basegrp, NULL, status ); /* Concatenate this continuous chunk */ smf_concat_smfGroup( wf, NULL, igroup, usedarks ? darks:NULL, bbms, flatramps, heateffmap, contchunk, ensureflat, 1, NULL, 0, NULL, NULL, NO_FTS, padStart, padEnd, 0, &concat, NULL, status ); if( *status == SAI__OK) { /* clean the dark squids now since we might need to use them to clean the bolometer data */ smf_get_cleanpar( keymap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dkclean, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, status ); for( idx=0; dkclean&&(*status==SAI__OK)&&idx<concat->ndat; idx++ ) { odata = concat->sdata[idx]; if( odata && odata->da && odata->da->dksquid ) { smfData *dksquid = odata->da->dksquid; AstKeyMap *kmap=NULL; msgOut("", TASK_NAME ": cleaning dark squids", status); /* fudge the header so that we can get at JCMTState */ dksquid->hdr = odata->hdr; /* clean darks using cleandk.* parameters */ astMapGet0A( keymap, "CLEANDK", &kmap ); array = smf_create_smfArray( status ); smf_addto_smfArray( array, dksquid, status ); smf_clean_smfArray( wf, array, NULL, NULL, NULL, kmap, status ); if( array ) { array->owndata = 0; smf_close_related( wf, &array, status ); } if( kmap ) kmap = astAnnul( kmap ); /* Unset hdr pointer so that we don't accidentally close it */ dksquid->hdr = NULL; } } /* Then the main data arrays */ if( *status == SAI__OK ) { smfArray *com = NULL; smfArray *gai = NULL; char filename[GRP__SZNAM+1]; msgOut("", TASK_NAME ": cleaning bolometer data", status ); smf_clean_smfArray( wf, concat, NULL, &com, &gai, keymap, status ); /* If ADAM parameters for COM or GAI were specified, and the common-mode was calculated, export to files here */ if( writecom && com ) { for( idx=0; (*status==SAI__OK)&&(idx<com->ndat); idx++ ) { smf_model_createHdr( com->sdata[idx], SMF__COM, concat->sdata[idx], status ); smf_stripsuffix( com->sdata[idx]->file->name, SMF__DIMM_SUFFIX, filename, status ); smf_dataOrder( wf, com->sdata[idx], 1, status ); smf_write_smfData( wf, com->sdata[idx], NULL, filename, NULL, 0, NDF__NOID, MSG__NORM, 0, NULL, NULL, status ); } } if( writegai && gai ) { for( idx=0; (*status==SAI__OK)&&(idx<gai->ndat); idx++ ) { smf_model_createHdr( gai->sdata[idx], SMF__GAI, concat->sdata[idx], status ); smf_stripsuffix( gai->sdata[idx]->file->name, SMF__DIMM_SUFFIX, filename, status ); smf_dataOrder( wf, gai->sdata[idx], 1, status ); smf_write_smfData( wf, gai->sdata[idx], NULL, filename, NULL, 0, NDF__NOID, MSG__NORM, 0, NULL, NULL, status ); } } /* Close com and gai */ if( com ) smf_close_related( wf, &com, status ); if( gai ) smf_close_related( wf, &gai, status ); } /* Report statistics (currently need a smfArray for that) */ if (*status == SAI__OK) { size_t last_qcount[SMF__NQBITS]; size_t last_nmap = 0; smf_qualstats_report( wf, MSG__VERB, SMF__QFAM_TSERIES, 1, concat, last_qcount, &last_nmap, 1, NULL, NULL, status ); } /* Clean up for contchunk loop */ if( keymap ) keymap = astAnnul( keymap ); } /* Export concatenated/cleaned data for each subarray to NDF file */ for( idx=0; (*status==SAI__OK)&&idx<concat->ndat; idx++ ) { odata = concat->sdata[idx]; /* Complete the history information in the output NDF so that it includes group parameters accessed since the default history information was written to the NDF (in smf_open_and_flatfield). */ smf_puthistory( odata, "SMURF:SC2CLEAN", status ); /* Ensure ICD data order */ smf_dataOrder( wf, odata, 1, status ); if( odata->file && odata->file->name ) { smf_write_smfData( wf, odata, NULL, NULL, ogrp, gcount, NDF__NOID, MSG__VERB, 0, NULL, NULL, status ); } else { *status = SAI__ERROR; errRep( FUNC_NAME, "Unable to determine file name for concatenated data.", status ); } /* Increment the group index counter */ gcount++; } /* Close the smfArray */ smf_close_related( wf, &concat, status ); } /* Write out the list of output NDF names, annulling the error if a null parameter value is supplied. */ if( *status == SAI__OK && ogrp ) { grpList( "OUTFILES", 0, 0, NULL, ogrp, status ); if( *status == PAR__NULL ) errAnnul( status ); } CLEANUP: /* Tidy up after ourselves: release the resources used by the grp routines */ if( darks ) smf_close_related( wf, &darks, status ); if( flatramps ) smf_close_related( wf, &flatramps, status ); if (heateffmap) heateffmap = smf_free_effmap( heateffmap, status ); if( bbms ) smf_close_related( wf, &bbms, status ); if( igrp ) grpDelet( &igrp, status); if( ogrp ) grpDelet( &ogrp, status); if( basegrp ) grpDelet( &basegrp, status ); if( igroup ) smf_close_smfGroup( &igroup, status ); fftw_cleanup(); ndfEnd( status ); }
int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; // Set up the PRNG dsfmt_t *dsfmt = malloc(sizeof(dsfmt_t)); if(dsfmt == NULL) { fprintf(stdout, "unable to allocate PRNG\n"); goto skip_deallocate_prng; } dsfmt_init_gen_rand(dsfmt, SEED); // Set up the source values double *src = fftw_malloc(N*VL*sizeof(double)); if(src == NULL) { fprintf(stdout, "unable to allocate source vector\n"); goto skip_deallocate_src; } for(unsigned int i = 0; i < N*VL; ++i) { src[i] = dsfmt_genrand_open_close(dsfmt); } // Allocate the FFT destination array double complex *fft = fftw_malloc(N*VL*sizeof(double complex)); if(fft == NULL) { fprintf(stdout, "unable to allocate fft vector\n"); goto skip_deallocate_fft; } // Execute the forward FFT fftw_plan fwd_plan = fftw_plan_many_dft_r2c(1, &N, VL, src, NULL, VL, 1, fft, NULL, VL, 1, FFTW_ESTIMATE); if(fwd_plan == NULL) { fprintf(stdout, "unable to allocate fft forward plan\n"); goto skip_deallocate_fwd_plan; } fftw_execute(fwd_plan); // Fill in the rest of the destination values using the Hermitian property. fft_r2c_1d_vec_finish(fft, N, VL); // Allocate the reverse FFT destination array double complex *dst = fftw_malloc(N*VL*sizeof(double complex)); if(dst == NULL) { fprintf(stdout, "unable to allocate dst vector\n"); goto skip_deallocate_dst; } // Perform the reverse FFT fftw_plan rev_plan = fftw_plan_many_dft(1, &N, VL, fft, NULL, VL, 1, dst, NULL, VL, 1, FFTW_BACKWARD, FFTW_ESTIMATE); if(rev_plan == NULL) { fprintf(stdout, "unable to allocate fft reverse plan\n"); goto skip_deallocate_rev_plan; } fftw_execute(rev_plan); // Compare the two vectors by sup norm double norm = 0.0; for(unsigned int i = 0; i < N*VL; ++i) { // Divide the resulting by N, because FFTW computes the un-normalized DFT: // the forward followed by reverse transform scales the data by N. norm = fmax(norm, cabs(dst[i]/N - src[i])); } if(norm <= 1e-6) { ret = EXIT_SUCCESS; } fftw_destroy_plan(rev_plan); skip_deallocate_rev_plan: fftw_free(dst); skip_deallocate_dst: fftw_destroy_plan(fwd_plan); skip_deallocate_fwd_plan: fftw_free(fft); skip_deallocate_fft: fftw_free(src); skip_deallocate_src: free(dsfmt); skip_deallocate_prng: // Keep valgrind happy by having fftw clean up its internal structures. This // helps ensure we aren't leaking memory. fftw_cleanup(); return ret; }