func output3D(D [][]complex64, reduce func(complex64) float32, size [3]int, prefix string, deltaF float32) { const NCOMP = 1 for i := 0; i < len(D)/2; i++ { d := D[i] MHz := int((float32(i) * deltaF) / 1e6) fname := fmt.Sprintf("%sf%06dMHz.ovf", prefix, MHz) slice := data.NewSlice(NCOMP, size) doReduce(slice.Host()[0], d, reduce) meta := data.Meta{} log.Println(fname) f := httpfs.MustCreate(fname) oommf.WriteOVF2(f, slice, meta, "binary") f.Close() } }
func mainSpatial() { // time points Nt := flag.NArg() if Nt < 2 { log.Fatal("need at least 2 inputs") } go loadloop() // select one component comp := 0 // todo // get size, time span from first and last file data1, meta1 := oommf.MustReadFile(flag.Args()[0]) _, metaL := oommf.MustReadFile(flag.Args()[Nt-1]) t0 := float32(meta1.Time) t1 := float32(metaL.Time) deltaT := t1 - t0 deltaF := 1 / deltaT // frequency resolution size := data1.Size() Nx := size[0] Ny := size[1] Nz := size[2] // allocate buffer for everything dataList := make([]complex64, Nt*Nx*Ny*Nz) dataLists := matrix.ReshapeC2(dataList, [2]int{Nt, Nz * Ny * Nx}) // interpolate non-equidistant time points // make complex in the meanwhile time0 := t0 // start time, not neccesarily 0 si := 0 // source index for di := 0; di < Nt; di++ { // dst index want := time0 + float32(di)*deltaT/float32(Nt) // wanted time for si < Nt-1 && !(time(si) <= want && time(si+1) > want && time(si) != time(si+1)) { si++ } x := (want - time(si)) / (time(si+1) - time(si)) if x < 0 || x > 1 { panic(fmt.Sprint("x=", x)) } interp3D(dataLists[di], 1-x, file(si).Host()[comp], x, file(si + 1).Host()[comp]) } log.Println("FFT") fftMany(dataList, Nt, Nx*Ny*Nz) spectrum := magSpectrum(dataLists) freqs := make([]float32, len(spectrum)) for i := range freqs { freqs[i] = float32(i) * deltaF } header := []string{"f (Hz)", "Mag ()"} f := httpfs.MustCreate("spectrum.txt") writeTable(f, header, [][]float32{freqs, spectrum}) f.Close() log.Println("normalize") normalize(dataLists) log.Println("output") for _, o := range outputs { if *o.Enabled { output3D(dataLists, o.Filter, size, "fft_"+o.Name, deltaF) } } }
// FFT a single table file func processTable(infname, outfname string) { // read input file in := httpfs.MustOpen(infname) defer in.Close() header, data := ReadTable(in) // Process data if *flag_Interp { data = interp(data) // interpolate to equidistant times } // determine frequency step, beware zero padding const TIME = 0 // time column rows := len(data[TIME]) deltaT := data[TIME][rows-1] - data[TIME][0] deltaT *= float32(*flag_Pad) deltaF := 1 / (deltaT) // mumax outputs one row too much rows-- for i := range data { data[i] = data[i][:rows] } window := windows[*flag_Win] if window == nil { panic(fmt.Sprint("invalid window:", *flag_Win, " options:", windows)) } for c := range data { applyWindow(data[c], window) data[c] = zeropad(data[c], rows*(*flag_Pad)) } transf := FFT(data[1:]) // FFT all but first (time) column if *flag_NormCol == 1 { errPrintln("-divcol may start at column 2") os.Exit(1) } if *flag_NormCol > 1 { divCol(transf, transf[*flag_NormCol-2]) } output := reduce(transf, deltaF) outHdr := makeFFTHeader(header) if *flag_CleanPhase { for c := range output[1:] { if strings.HasPrefix(outHdr[c], "Ph_") { cleanPhase(output[c]) } } } // write output file var out io.Writer if *flag_Stdout { out = os.Stdout } else { o := httpfs.MustCreate(outfname) defer o.Close() out = o } writeTable(out, outHdr, output) }