Skip to content

Commit

Permalink
add assign-geometry tool
Browse files Browse the repository at this point in the history
  • Loading branch information
thisisaaronland committed Jun 4, 2021
1 parent 06a32c2 commit d3970e3
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 14 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
cli:
go build -mod vendor -o bin/assign-geometry cmd/assign-geometry/main.go
go build -mod vendor -o bin/assign-parent cmd/assign-parent/main.go
go build -mod vendor -o bin/exportify cmd/exportify/main.go
go build -mod vendor -o bin/create cmd/create/main.go
Expand Down
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,58 @@ $> ./bin/as-featurecollection \
1729792699
```

### assign-geometry

Assign the geometry from a given record to one or more other records.

```
$> ./bin/assign-geometry -h
Assign the geometry from a given record to one or more other records.
Usage:
./bin/assign-geometry [options] target-id-(N) target-id-(N)
For example:
./bin/assign-geometry -reader-uri fs:///usr/local/data/whosonfirst-data-admin-ca/data -source-id 1234 5678
Valid options are:
-exporter-uri string
A valid whosonfirst/go-whosonfirst-export URI (default "whosonfirst://")
-reader-uri string
A valid whosonfirst/go-reader URI.
-source-id int
A valid Who's On First ID.
-stdin
Read target IDs from STDIN
-writer-uri string
A valid whosonfirst/go-writer URI. (default "stdout://")
```

_This tool can (and probably be should) be adapted in the general-purpose assign properties or geometry tool. Today it only handles geometries._

For example:

```
$> /usr/local/whosonfirst/go-whosonfirst-travel/bin/wof-travel-id \
-supersedes \
-ids \
-source fs:///usr/local/data/sfomuseum-data-architecture/data \
1729813675 \
| bin/assign-geometry \
-stdin \
-reader-uri fs:///usr/local/data/sfomuseum-data-architecture/data \
-writer-uri fs:///usr/local/data/sfomuseum-data-architecture/data \
-source-id 1729813675
```

This is a fairly involved example, so here's a description of what's happening:

* First we are using the `wof-travel-id` tool in the [go-whosonfirst-travel](https://github.com/whosonfirst/go-whosonfirst-travel) package to find all the records that, recursively, ID `1729813675` supersedes.
* We are exporting that list as a line-separated list of IDs (having specified the `-ids` flag).
* We are piping that output to the `assign-geometry` tool and reading the list of IDs from `STDIN` (having specified the `-stdin` flag).
* For each of those IDs we are assigning the geometry from the record with the ID `1729813675` and writing those updates back to disk.

### assign-parent

```
Expand Down
139 changes: 139 additions & 0 deletions cmd/assign-geometry/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Assign the geometry from a given record to one or more other records.
package main

// This could (should) be extended to be a basic assign <properties or geometry> tool.

import (
"bufio"
"context"
"flag"
"github.com/whosonfirst/go-reader"
"github.com/whosonfirst/go-whosonfirst-export/v2"
wof_reader "github.com/whosonfirst/go-whosonfirst-reader"
wof_writer "github.com/whosonfirst/go-whosonfirst-writer"
"github.com/whosonfirst/go-writer"
"log"
"os"
"strconv"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"fmt"
)

func main() {

reader_uri := flag.String("reader-uri", "", "A valid whosonfirst/go-reader URI.")
writer_uri := flag.String("writer-uri", "stdout://", "A valid whosonfirst/go-writer URI.")

exporter_uri := flag.String("exporter-uri", "whosonfirst://", "A valid whosonfirst/go-whosonfirst-export URI")

source_id := flag.Int64("source-id", 0, "A valid Who's On First ID.")

from_stdin := flag.Bool("stdin", false, "Read target IDs from STDIN")

flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Assign the geometry from a given record to one or more other records.\n\n")
fmt.Fprintf(os.Stderr, "Usage:\n\t %s [options] target-id-(N) target-id-(N)\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, "For example:\n")
fmt.Fprintf(os.Stderr, "\t%s -reader-uri fs:///usr/local/data/whosonfirst-data-admin-ca/data -source-id 1234 5678\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, "Valid options are:\n")
flag.PrintDefaults()
}

flag.Parse()

// START OF put me in a function...

str_ids := flag.Args()

if *from_stdin {

scanner := bufio.NewScanner(os.Stdin)

for scanner.Scan() {
str_ids = append(str_ids, scanner.Text())
}

err := scanner.Err()

if err != nil {
log.Fatalf("Failed to read input from STDIN, %v", err)
}
}

target_ids := make([]int64, len(str_ids))

for idx, this_id := range str_ids {

id, err := strconv.ParseInt(this_id, 10, 64)

if err != nil {
log.Fatalf("Failed to parse '%s', %v", this_id, err)
}

target_ids[idx] = id
}

// END OF put me in a function

ctx := context.Background()

r, err := reader.NewReader(ctx, *reader_uri)

if err != nil {
log.Fatalf("Failed to create reader for '%s', %v", *reader_uri, err)
}

wr, err := writer.NewWriter(ctx, *writer_uri)

if err != nil {
log.Fatalf("Failed to create new writer for '%s', %v", *writer_uri, err)
}

ex, err := export.NewExporter(ctx, *exporter_uri)

if err != nil {
log.Fatalf("Failed to create new exporter for '%s', %v", *exporter_uri, err)
}

source_body, err := wof_reader.LoadBytesFromID(ctx, r, *source_id)

if err != nil {
log.Fatalf("Failed to load source '%d', %v", *source_id)
}

geom_rsp := gjson.GetBytes(source_body, "geometry")

if !geom_rsp.Exists() {
log.Fatal("Source record is missing a geometry")
}

source_geom := geom_rsp.Value()

for _, id := range target_ids {

target_body, err := wof_reader.LoadBytesFromID(ctx, r, id)

if err != nil {
log.Fatalf("Failed to load target '%d', %v", id)
}

new_body, err := sjson.SetBytes(target_body, "geometry", source_geom)

if err != nil {
log.Fatalf("Failed to update target geometry for '%d', %v", id, err)
}

new_body, err = ex.Export(ctx, new_body)

if err != nil {
log.Fatalf("Failed to export target '%d', %v", id, err)
}

err = wof_writer.WriteFeatureBytes(ctx, wr, new_body)

if err != nil {
log.Fatalf("Failed to write target '%d', %v", id, err)
}
}
}
4 changes: 2 additions & 2 deletions cmd/create/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func main() {

results_cb := hierarchy.FirstButForgivingSPRResultsFunc
update_cb := hierarchy.DefaultPointInPolygonHierarchyResolverUpdateCallback()

new_body, err := resolver.PointInPolygonAndUpdate(ctx, inputs, results_cb, update_cb, body)

if err != nil {
Expand All @@ -208,7 +208,7 @@ func main() {
}

id_rsp := gjson.GetBytes(new_body, "properties.wof:id")

err = wof_writer.WriteFeatureBytes(ctx, wr, new_body)

if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions cmd/deprecate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/sfomuseum/go-flags/multi"
"github.com/whosonfirst/go-reader"
"github.com/whosonfirst/go-whosonfirst-export/v2"
"github.com/whosonfirst/go-whosonfirst-exportify"
"github.com/whosonfirst/go-whosonfirst-exportify"
wof_reader "github.com/whosonfirst/go-whosonfirst-reader"
"github.com/whosonfirst/go-writer"
"log"
Expand Down Expand Up @@ -126,17 +126,17 @@ func deprecateId(ctx context.Context, r reader.Reader, wr writer.Writer, ex expo
}

now := time.Now()

to_update := map[string]interface{}{
"properties.edtf:deprecated": now.Format("2006-01-02"),
"properties.mz:is_current": 0,
"properties.mz:is_current": 0,
}

new_body, err := export.AssignProperties(ctx, body, to_update)

if err != nil {
return err
}

return exportify.ExportWithWriter(ctx, ex, wr, new_body)
}
15 changes: 7 additions & 8 deletions cmd/rename-property/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import (
"context"
"flag"
_ "github.com/sfomuseum/go-flags/multi"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"github.com/whosonfirst/go-whosonfirst-export/v2"
"github.com/whosonfirst/go-whosonfirst-iterate/emitter"
"github.com/whosonfirst/go-whosonfirst-iterate/iterator"
wof_writer "github.com/whosonfirst/go-whosonfirst-writer"
"github.com/whosonfirst/go-writer"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"io"
"io/ioutil"
"log"
Expand All @@ -23,7 +23,7 @@ func main() {
writer_uri := flag.String("writer-uri", "null://", "A valid whosonfirst/go-writer URI.")

old_property := flag.String("old-property", "", "The fully qualified path of the property to rename.")
new_property := flag.String("new-property", "", "The fully qualified path of the property to be (re)named.")
new_property := flag.String("new-property", "", "The fully qualified path of the property to be (re)named.")

flag.Parse()

Expand Down Expand Up @@ -57,7 +57,7 @@ func main() {

old_rsp := gjson.GetBytes(body, *old_property)

if !old_rsp.Exists(){
if !old_rsp.Exists() {
return nil
}

Expand All @@ -67,12 +67,12 @@ func main() {
return err
}

body, err = sjson.DeleteBytes(body, *old_property)
body, err = sjson.DeleteBytes(body, *old_property)

if err != nil {
return err
}

new_body, err := ex.Export(ctx, body)

if err != nil {
Expand Down Expand Up @@ -106,4 +106,3 @@ func main() {
log.Fatal(err)
}
}

0 comments on commit d3970e3

Please sign in to comment.