func WriteAsciiBTL2(nc *lib.Nc, map_format map[string]string, hdr []string, inst string) {
	// define 2 files, profiles header and data
	var asciiFilename string

	// build filenames
	str := nc.Attributes["cycle_mesure"]
	str = strings.Replace(str, "\r", "", -1)
	headerFilename := fmt.Sprintf("output/%s."+inst, strings.ToLower(str))
	asciiFilename = fmt.Sprintf("output/%s%s_"+inst, strings.ToLower(str), prefixAll)
	//fmt.Println(headerFilename)
	//fmt.Println(asciiFilename)

	// open header file for writing result
	fid_hdr, err := os.Create(headerFilename)
	if err != nil {
		log.Fatal(err)
	}
	defer fid_hdr.Close()

	// use buffered mode for writing
	fbuf_hdr := bufio.NewWriter(fid_hdr)

	// open ASCII file for writing result
	fid_ascii, err := os.Create(asciiFilename)
	if err != nil {
		log.Fatal(err)
	}
	defer fid_ascii.Close()

	// use buffered mode for writing
	fbuf_ascii := bufio.NewWriter(fid_ascii)

	// write header to string
	str = fmt.Sprintf("%s  %s  %s  %s %s  %s\n",
		nc.Attributes["cycle_mesure"],
		nc.Attributes["plateforme"],
		nc.Attributes["institute"],
		nc.Attributes["type_instrument"],
		nc.Attributes["instrument_number"],
		nc.Attributes["pi"])

	// write first line header on header file and ascii file
	fmt.Fprintf(fbuf_hdr, str)
	fmt.Fprintf(fbuf_ascii, str)

	// display on screen
	fmt.Printf("%s", str)

	// write physical parameters in second line
	str = ""
	for _, key := range hdr {
		fmt.Fprintf(fbuf_ascii, "%s   ", key)
		fmt.Fprintf(debug, "%s   ", key)
	}
	// append new line
	//fmt.Fprintln(fbuf_ascii, "\n")

	// write second line header on ascii file
	fmt.Fprintln(fbuf_ascii, str)

	// display on screen
	fmt.Printf("%s", str)

	// get data (slices) from nc struct
	len_1D := nc.Dimensions["TIME"]
	len_2D := nc.Dimensions["DEPTH"]
	time := nc.Variables_1D["TIME"].([]float64)
	lat := nc.Variables_1D["LATITUDE"].([]float64)
	lon := nc.Variables_1D["LONGITUDE"].([]float64)
	profile := nc.Variables_1D["PROFILE"].([]float64)
	bath := nc.Variables_1D["BATH"].([]float64)

	// loop over each profile
	for x := 0; x < len_1D; x++ {
		str = ""
		// write profile informations to ASCII data file with DEPTH = -1
		t1 := NewTimeFromJulian(time[x])
		t2 := NewTimeFromJulianDay(nc.Extras_f[fmt.Sprintf("ETDD:%d", int(profile[x]))], t1)
		// TODOS: adapt profile format to stationPrefixLength
		fmt.Fprintf(fbuf_ascii, "%05.0f %4d %f %f %f %s",
			profile[x],
			codeForProfile,
			t1.JulianDayOfYear(),
			lat[x],
			lon[x],
			t1.Format("20060102150405"))

		// write profile informations to header file, max depth CTD and
		// bathymetrie are in meters
		str = fmt.Sprintf("%05.0f %s %s %s %s %4.4g %4.4g %s %s %s\n",
			profile[x],
			t1.Format("02/01/2006 15:04:05"),
			t2.Format("02/01/2006 15:04:05"),
			DecimalPosition2String(lat[x], 0),
			DecimalPosition2String(lon[x], 0),
			nc.Extras_f[fmt.Sprintf("DEPTH:%d", int(profile[x]))],
			bath[x],
			nc.Extras_s[fmt.Sprintf("TYPECAST:%s", int(profile[x]))],
			cfg.Ctd.CruisePrefix+nc.Extras_s[fmt.Sprintf("PRFL_NAME:%d", int(profile[x]))])

		// write profile information to header file
		fmt.Fprintf(fbuf_hdr, str)

		// display on screen
		fmt.Printf("%s", str)

		// fill last header columns with 1e36
		for i := 0; i < len(hdr)-6; i++ {
			fmt.Fprintf(fbuf_ascii, " %g", 1e36)
		}
		fmt.Fprintln(fbuf_ascii) // add newline

		// loop over each level
		for y := 0; y < len_2D; y++ {
			// goto next profile when max depth reach
			if lib.GetData(nc.Variables_2D["PRES"])[x][y] >=
				nc.Extras_f[fmt.Sprintf("PRES:%d", int(profile[x]))] {
				continue
			}
			fmt.Fprintf(fbuf_ascii, "%05.0f ", profile[x])
			// loop over each physical parameter (key) in the rigth order
			for _, key := range hdr {
				// if key not in map, goto next key
				if _, ok := nc.Variables_2D[key]; ok {
					// fill 2D slice
					data := lib.GetData(nc.Variables_2D[key])[x][y]
					// print data with it's format, change format for FillValue
					if data == 1e36 {
						fmt.Fprintf(fbuf_ascii, "%g ", data)
					} else {
						fmt.Fprintf(fbuf_ascii, map_format[key]+" ", data)
					}
				}
			}
			fmt.Fprintf(fbuf_ascii, "\n")

		}
		fbuf_ascii.Flush()
		fbuf_hdr.Flush()
	}
}
Beispiel #2
0
// creates the NetCDF file following nc structure.
//func WriteNetcdf(any interface{}) error {
func WriteNetcdf(nc *lib.Nc, m *config.Map, ncType string) {

	// build filename
	filename := fmt.Sprintf("output/OS_%s%s_%s.nc",
		strings.ToUpper(nc.Attributes["cycle_mesure"]),
		strings.ToUpper(prefixAll),
		ncType)
	//fmt.Println(filename)

	// get roscop definition file for variables attributes
	var roscop = nc.Roscop
	//	for k, v := range roscop {
	//		fmt.Printf("%s: ", k)
	//		fmt.Println(v)
	//	}
	//	os.Exit(0)

	fmt.Fprintf(echo, "writing netCDF: %s\n", filename)

	// get variables_1D size
	len_1D := nc.Dimensions["TIME"]
	len_2D := nc.Dimensions["DEPTH"]

	// Create a new NetCDF 3 file. The dataset is returned.
	ds, err := netcdf.CreateFile(filename, netcdf.CLOBBER)
	if err != nil {
		log.Fatal(err)
	}
	defer ds.Close()

	// Add the dimensions for our data to the dataset
	dim_1D := make([]netcdf.Dim, 1)
	dim_2D := make([]netcdf.Dim, 2)

	// dimensions for ROSCOP paremeters as DEPTH, PRES, TEMP, PSAL, etc
	dim_2D[0], err = ds.AddDim("TIME", uint64(len_1D))
	if err != nil {
		log.Fatal(err)
	}
	dim_2D[1], err = ds.AddDim("DEPTH", uint64(len_2D))
	if err != nil {
		log.Fatal(err)
	}
	// dimension for PROFILE, LATITUDE, LONGITUDE and BATH
	dim_1D[0] = dim_2D[0]

	// Add the variable to the dataset that will store our data
	map_1D := make(map[string]netcdf.Var)
	for key, _ := range nc.Variables_1D {
		v, err := ds.AddVar(key, netcdf.DOUBLE, dim_1D)
		if err != nil {
			log.Fatal(err)
		}
		map_1D[key] = v

		//initialise struct roscop with netcdf variable in reflect ways without knowing the form of the roscop struct
		Reflectroscop(roscop[key], map_1D[key])

	}

	map_2D := make(map[string]netcdf.Var)

	// use the order list gave by split or splitAll (config file) because
	// the iteration order is not specified and is not guaranteed to be
	// the same from one iteration to the next in golang
	// for key, _ := range nc.Variables_2D {
	for _, key := range m.Hdr {
		// remove PRFL from the key list
		if key == "PRFL" {
			continue
		}
		v, err := ds.AddVar(key, netcdf.DOUBLE, dim_2D)
		if err != nil {
			log.Fatal(err)
		}
		map_2D[key] = v

		//initialise struct roscop with netcdf variable in reflect ways without knowing the form of the roscop struct
		Reflectroscop(roscop[key], map_2D[key])

	}

	// defines global attributes
	for key, value := range nc.Attributes {
		a := ds.Attr(key)
		a.WriteBytes([]byte(value))
	}

	// leave define mode in NetCDF3
	ds.EndDef()

	// Create the data with the above dimensions and write it to the file.
	for key, value := range nc.Variables_1D {

		v := value.([]float64)
		fmt.Fprintf(echo, "writing %s: %d\n", key, len(v))
		err = map_1D[key].WriteFloat64s(v)
		if err != nil {
			log.Fatal(err)
		}
	}

	// write data 2D (value.data) to netcdf variables
	// for key, value := range nc.Variables_2D {
	for _, key := range m.Hdr {
		// remove PRFL from the key list
		if key == "PRFL" {
			continue
		}
		value := nc.Variables_2D[key]
		i := 0
		ht := len(lib.GetData(value))
		wd := len(lib.GetData(value)[0])
		fmt.Fprintf(echo, "writing %s: %d x %d\n", key, ht, wd)
		fmt.Fprintf(debug, "writing %s: %d x %d\n", key, ht, wd)
		// Write<type> netcdf methods need []<type>, [][]data will be flatten
		gopher := make([]float64, ht*wd)
		for x := 0; x < ht; x++ {
			for y := 0; y < wd; y++ {
				gopher[i] = lib.GetData(value)[x][y]
				i++
			}
		}
		err = map_2D[key].WriteFloat64s(gopher)
		if err != nil {
			log.Fatal(err)
		}
	}
	fmt.Fprintf(echo, "writing %s done ...\n", filename)
	//return nil
}