Example #1
0
// on the PC
//  go run grump-reader.go -tkvdata="C:\Users\peugeot\tkv-data"
func main() {

	// flag "country"
	countryPtr := flag.String("country", "fra", "iso 3166 country code")
	targetMaxBodiesPtr := flag.String("targetMaxBodies", "100000", "target nb of bodies")

	// get the directory containing tkv data through the flag "tkvdata"
	dirTKVDataPtr := flag.String("tkvdata", "/Users/thomaspeugeot/the-mapping-data/", "directory containing input tkv data")

	var country grump.Country

	flag.Parse()

	{
		_, errScan := fmt.Sscanf(*targetMaxBodiesPtr, "%d", &targetMaxBodies)
		if errScan != nil {
			log.Fatal(errScan)
			return
		}
	}

	grump.Info.Printf("country to parse %s", *countryPtr)
	country.Name = *countryPtr
	grump.Info.Printf("directory containing tkv data %s", *dirTKVDataPtr)
	dirTKVData := *dirTKVDataPtr

	// create the path to the agragate country count
	grumpFilePath := fmt.Sprintf("%s/%s_grumpv1_pcount_00_ascii_30/%sup00ag.asc", dirTKVData, *countryPtr, *countryPtr)
	grump.Info.Printf("relative path %s", filepath.Clean(grumpFilePath))
	var grumpFile *os.File
	var err error
	grumpFile, err = os.Open(filepath.Clean(grumpFilePath))
	if err != nil {
		log.Fatal(err)
	}

	// parse the grump
	var word int
	scanner := bufio.NewScanner(grumpFile)
	scanner.Split(bufio.ScanWords)

	// scan 8 first lines
	scanner.Scan()
	scanner.Scan()
	fmt.Sscanf(scanner.Text(), "%d", &country.NCols)
	scanner.Scan()
	scanner.Scan()
	fmt.Sscanf(scanner.Text(), "%d", &country.NRows)
	scanner.Scan()
	scanner.Scan()
	fmt.Sscanf(scanner.Text(), "%d", &country.XllCorner)
	scanner.Scan()
	scanner.Scan()
	fmt.Sscanf(scanner.Text(), "%d", &country.YllCorner)

	country.Serialize()
	grump.Info.Println("country struct content is ", country)

	// scan the reamining header
	for word < 4 {
		scanner.Scan()
		word++
		fmt.Println(fmt.Sprintf("item %d : %s", word, scanner.Text()))
	}
	colLngWidth := 0.0083333333333

	// prepare the count matrix
	countMatrix := make([]float64, country.NRows*country.NCols)

	popTotal := 0.0
	// scan the file and store result in countMatrix
	for row := 0; row < country.NRows; row++ {
		lat := country.Row2Lat(row)
		for col := 0; col < country.NCols; col++ {
			scanner.Scan()
			// lng := float64(country.XllCorner) + (float64(col)*colLngWidth)

			var count float64
			fmt.Sscanf(scanner.Text(), "%f", &count)
			popTotal += count

			countMatrix[(country.NRows-row-1)*country.NCols+col] = count

		}
		fmt.Printf("\rrow %5d lat %2.3f total %f", row, lat, popTotal)
	}
	fmt.Printf("\n")
	grump.Info.Printf("reading grump file is over, closing")
	grumpFile.Close()

	// get the arrangement
	arrangements := make(arrangementsStore, maxCirclePerCell+1)
	for nbCircles := 1; nbCircles <= maxCirclePerCell; nbCircles++ {

		fmt.Printf("\rgetting arrangement for %3d circles", nbCircles)

		arrangements[nbCircles] = make([]circleCoord, nbCircles)

		// open the reference file
		circlePackingFilePath := fmt.Sprintf("%s/csq_coords/csq%d.txt", dirTKVData, nbCircles)
		var circlePackingFile *os.File
		var errCirclePackingFile error
		circlePackingFile, errCirclePackingFile = os.Open(filepath.Clean(circlePackingFilePath))
		if errCirclePackingFile != nil {
			log.Fatal(err)
		}

		// prepare scanner
		scannerCircle := bufio.NewScanner(circlePackingFile)
		scannerCircle.Split(bufio.ScanWords)

		// one line per circle
		for circle := 0; circle < nbCircles; circle++ {

			// scan the id of the circle
			scannerCircle.Scan()

			// scan X coordinate
			scannerCircle.Scan()
			fmt.Sscanf(scannerCircle.Text(), "%f", &(arrangements[nbCircles][circle].x))
			// scan Y coordinate
			scannerCircle.Scan()
			fmt.Sscanf(scannerCircle.Text(), "%f", &(arrangements[nbCircles][circle].y))
			// fmt.Printf("getting arrangement for %d circle %3d, coord %f %f\n", nbCircles, circle, arrangements[nbCircles][circle].x, arrangements[nbCircles][circle].y)
		}
		circlePackingFile.Close()
	}
	grump.Info.Printf("reading circle packing files is over")

	// prepare the output density file
	var bodies []quadtree.Body
	bodiesInCellMax := 0

	grump.Info.Printf("Preparing the ouput")
	cumulativePopTotal := 0.0
	bodiesNb := 0
	for row := 0; row < country.NRows; row++ {
		lat := country.Row2Lat(row)
		for col := 0; col < country.NCols; col++ {
			lng := float64(country.XllCorner) + (float64(col) * colLngWidth)

			// compute relative coordinate of the cell
			relX, relY := country.LatLng2XY(lat, lng)

			// fetch count of the cell
			count := countMatrix[row*country.NCols+col]

			// how many bodies ? it is maxBodies *( count / country.PCount)
			bodiesInCell := int(math.Floor(float64(targetMaxBodies) * count / popTotal))

			massPerBody := float64(count) / float64(bodiesInCell)

			if bodiesInCell > bodiesInCellMax {
				bodiesInCellMax = bodiesInCell
			}

			if bodiesInCell > maxCirclePerCell {
				grump.Error.Printf("bodiesInCell %d superior to maxCirclePerCell %d", bodiesInCell, maxCirclePerCell)

				bodiesInCell = maxCirclePerCell
				massPerBody = float64(count) / float64(bodiesInCell)
			}

			// initiate the bodies
			for i := 0; i < bodiesInCell; i++ {
				var body quadtree.Body
				// angle := float64(i) * 2.0 * math.Pi / float64(bodiesInCell)
				body.X = relX + (1.0/float64(country.NCols))*(0.5+arrangements[bodiesInCell][i].x)
				body.Y = relY + (1.0/float64(country.NRows))*(0.5+arrangements[bodiesInCell][i].y)
				body.M = massPerBody

				bodies = append(bodies, body)
			}
			cumulativePopTotal += count
			bodiesNb += bodiesInCell
		}
	}

	// var quadtree quadtree.Quadtree
	// quadtree.Init( &bodies)
	fmt.Println("bodies in cell max ", bodiesInCellMax)
	fmt.Println("cumulative pop ", cumulativePopTotal)
	fmt.Println("nb of bodies ", bodiesNb)

	var run barnes_hut.Run
	run.Init(&bodies)
	run.OutputDir = "."
	run.SetCountry(country.Name)

	run.CaptureConfig()
}
Example #2
0
// compute repulsion field at interpolation point x, y and update v
func (f *RepulsionField) ComputeFieldRecursive(x, y float64, q *quadtree.Quadtree, coord quadtree.Coord, v *float64) {

	Trace.Printf("ComputeFieldRecursive at %e %e, quadtree %p, coord %s, input v = %e\n", x, y, q, coord.String(), *v)

	var body quadtree.Body
	body.X = x
	body.Y = y

	// compute the node box size
	level := coord.Level()
	boxSize := 1.0 / math.Pow(2.0, float64(level)) // if level = 0, this is 1.0

	node := &(q.Nodes[coord])
	distToNode := getModuloDistanceBetweenBodies(&body, &(node.Body))

	// avoid node with zero mass
	if node.M == 0 {
		return
	}

	// check if the COM of the node can be used
	if (boxSize / distToNode) < BN_THETA {

		*v += getRepulsionField(&body, &(node.Body))

	} else {
		if level < 8 {
			// parse sub nodes
			Trace.Printf("ComputeFieldRecursive go down at node %#v\n", node.Coord())

			coordNW, coordNE, coordSW, coordSE := quadtree.NodesBelow(coord)
			f.ComputeFieldRecursive(x, y, q, coordNW, v)
			f.ComputeFieldRecursive(x, y, q, coordNE, v)
			f.ComputeFieldRecursive(x, y, q, coordSW, v)
			f.ComputeFieldRecursive(x, y, q, coordSE, v)
		} else {

			// parse bodies of the node
			rank := 0
			rankOfBody := -1
			for b := node.First(); b != nil; b = b.Next() {
				if *b != body {

					dist := getModuloDistanceBetweenBodies(&body, b)

					if dist == 0.0 {
						var t testing.T
						q.CheckIntegrity(&t)

						// c1 := body.Coord()
						// c2 := b.Coord()
						Error.Printf("Problem at rank %d for body of rank %d on node %#v ",
							rank, rankOfBody, *node)
					}

					// if distance is inferior to cutoff, return
					if dist < f.cutoff {
						*v = 0.0
						return

					} else {
						*v += getRepulsionField(&body, b)

					}

					rank++
					Trace.Printf("ComputeFieldRecursive at leaf %#v rank %d x %9.3f y %9.3f\n", b.Coord(), rank, x, y)
				} else {
					rankOfBody = rank
				}
			}
		}
	}
	return
}