Skip to content

Commit

Permalink
aep: Fix hash key
Browse files Browse the repository at this point in the history
  • Loading branch information
ctessum committed Nov 11, 2019
1 parent bd9f326 commit 0e457f0
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 56 deletions.
7 changes: 4 additions & 3 deletions emissions/aep/coards_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ func ReadCOARDSFile(file string, begin, end time.Time, units InputUnits, sourceD
max := geom.Point{X: x + dx/2, Y: y + dy/2}

r := &basicPolygonRecord{
Polygon: geom.Polygon{{min, {max.X, min.Y}, max, {min.X, max.Y}}},
SourceData: sourceData,
SR: sr,
Polygon: geom.Polygon{{min, {X: max.X, Y: min.Y}, max, {X: min.X, Y: max.Y}}},
SourceData: sourceData,
SR: sr,
LocationName: fmt.Sprintf("%d_%d", j, i),
}

e := new(Emissions)
Expand Down
13 changes: 11 additions & 2 deletions emissions/aep/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ func init() {

type Location struct {
geom.Geom
SR *proj.SR
SR *proj.SR
Name string
}

func (l *Location) String() string {
if l.Name == "" {
panic("location must have name")
}
return l.Name
}

func (l *Location) Reproject(sr *proj.SR) (geom.Geom, error) {
Expand Down Expand Up @@ -155,6 +163,7 @@ type basicPolygonRecord struct {
SR *proj.SR
SourceData
Emissions
LocationName string
}

// PointData exists to fulfill the Record interface but always returns
Expand All @@ -163,7 +172,7 @@ func (r *basicPolygonRecord) PointData() *PointSourceData { return nil }

// Location returns the polygon representing the location of emissions.
func (r *basicPolygonRecord) Location() *Location {
return &Location{r.Polygon, r.SR}
return &Location{Geom: r.Polygon, SR: r.SR, Name: r.LocationName}
}

type supplementalPointRecord struct {
Expand Down
2 changes: 1 addition & 1 deletion emissions/aep/pointsourcedata.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func (r *PointSourceData) StackParameters() (StackHeight, StackDiameter, StackTe
}

func (r *PointSourceData) Location() *Location {
return &Location{r.Point, r.SR}
return &Location{Geom: r.Point, SR: r.SR, Name: fmt.Sprintf("%v", r.Point)}
}

// GroundLevel returns true if the receiver emissions are
Expand Down
2 changes: 1 addition & 1 deletion emissions/aep/sourcedata.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (sdl *sourceDataLocator) Locate(sd *SourceDataLocation) error {
return err
}
if _, ok := sdl.inputShapes[srgSpec]; !ok {
sdl.inputShapes[srgSpec], err = srgSpec.(*SrgSpecSMOKECache).InputShapes()
sdl.inputShapes[srgSpec], err = srgSpec.(*SrgSpecSMOKE).InputShapes()
if err != nil {
return err
}
Expand Down
5 changes: 2 additions & 3 deletions emissions/aep/spatialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import (
"github.com/ctessum/requestcache"
"github.com/ctessum/sparse"
"github.com/ctessum/unit"
"github.com/spatialmodel/inmap/internal/hash"
)

// SpatialProcessor spatializes emissions records.
Expand Down Expand Up @@ -262,7 +261,7 @@ func (sp *SpatialProcessor) Surrogate(srgSpec SrgSpec, grid *GridDef, loc *Locat
sp.lazyLoad.Do(sp.load)

s := &srgGrid{srg: srgSpec, gridData: grid, loc: loc}
req := sp.cache.NewRequest(context.Background(), s, "surrogate_"+hash.Hash(s))
req := sp.cache.NewRequest(context.Background(), s, s.key())
resultI, err := req.Result()
if err != nil {
return nil, false, err
Expand All @@ -279,7 +278,7 @@ func (sp *SpatialProcessor) Surrogate(srgSpec SrgSpec, grid *GridDef, loc *Locat
return nil, false, err
}
s := &srgGrid{srg: newSrgSpec, gridData: grid, loc: loc}
req := sp.cache.NewRequest(context.Background(), s, "surrogate_"+hash.Hash(s))
req := sp.cache.NewRequest(context.Background(), s, s.key())
resultI, err := req.Result()
if err != nil {
return nil, false, err
Expand Down
112 changes: 110 additions & 2 deletions emissions/aep/spatialize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"context"
"fmt"
"math"
"reflect"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -76,7 +77,7 @@ func TestReadSrgSpec(t *testing.T) {
if err != nil {
t.Fatal(err)
}
srgSpec := srgSpecI.(*SrgSpecSMOKECache)
srgSpec := srgSpecI.(*SrgSpecSMOKE)
testResult += fmt.Sprintf("&{Region:%s Name:%s Code:%s DATASHAPEFILE:%s "+
"DATAATTRIBUTE:%s WEIGHTSHAPEFILE:%s Details:%s "+
"BackupSurrogateNames:%v WeightColumns:%v MergeNames:%v MergeMultipliers:%v}\n",
Expand Down Expand Up @@ -201,7 +202,7 @@ func TestCreateSurrogates(t *testing.T) {
if err != nil {
t.Fatal(err)
}
inputShapes, err := srgSpec.(*SrgSpecSMOKECache).InputShapes()
inputShapes, err := srgSpec.(*SrgSpecSMOKE).InputShapes()
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -382,3 +383,110 @@ func TestSpatializeRecord(t *testing.T) {
}
}
}

// Test to make sure surrogate cache is working
func TestSpatializeRecord_srgCache(t *testing.T) {
inputSR, err := proj.Parse("+proj=longlat")
if err != nil {
t.Error(err)
}
r := strings.NewReader(srgSpecFileString)
srgSpecs, err := ReadSrgSpecSMOKE(r, "testdata", true, "", 1)
if err != nil {
t.Error(err)
}
r = strings.NewReader(gridRefFileString)
gridRef, err := ReadGridRef(r, true)
if err != nil {
t.Fatal(err)
}
grid, err := createGrid()
if err != nil {
t.Fatal(err)
}
sp := NewSpatialProcessor(srgSpecs, []*GridDef{grid}, gridRef, inputSR, true)
//sp.DiskCachePath = "testcache"

sdl := newSourceDataLocator(gridRef, srgSpecs)

emis := new(Emissions)
begin, _ := time.Parse("Jan 2006", "Jan 2005")
end, _ := time.Parse("Jan 2006", "Jan 2006")
rate, err := parseEmisRateAnnual("1", "-9", func(v float64) *unit.Unit { return unit.New(v, unit.Kilogram) })
if err != nil {
t.Fatal(err)
}
emis.Add(begin, end, "testpol", "", rate)

rec := &PolygonRecord{
SourceDataLocation: SourceDataLocation{SourceData: SourceData{
FIPS: "36061",
SCC: "0010200501",
Country: USA,
}},
Emissions: *emis,
}
sdl.Locate(rec.getSourceDataLocation())
srgRec := sp.AddSurrogate(rec)

for i := 0; i < 3; i++ {
gr := sp.GridRecord(srgRec)
_, _, err = gr.GriddedEmissions(begin, end, 0)
if err != nil {
t.Fatal(err)
}

requestsWant := []int{i + 1, i + 1, 1}
requests := sp.cache.Requests()
if !reflect.DeepEqual(requests, requestsWant) {
t.Errorf("%d: %v != %v", i, requests, requestsWant)
}

srgSpec, err := srgRec.SurrogateSpecification()
if err != nil {
t.Fatal(err)
}

requestsWant = []int{1, 1, 1}
requests = srgSpec.(*SrgSpecSMOKE).cache.Requests()
if !reflect.DeepEqual(requests, requestsWant) {
t.Errorf("%d: %v != %v", i, requests, requestsWant)
}
}

rec2 := &PolygonRecord{
SourceDataLocation: SourceDataLocation{SourceData: SourceData{
FIPS: "36047",
SCC: "0010200501",
Country: USA,
}},
Emissions: *emis,
}
sdl.Locate(rec2.getSourceDataLocation())
srgRec2 := sp.AddSurrogate(rec2)

for i := 0; i < 2; i++ {
gr := sp.GridRecord(srgRec2)
_, _, err = gr.GriddedEmissions(begin, end, 0)
if err != nil {
t.Fatal(err)
}

requestsWant := []int{i + 4, i + 4, 2}
requests := sp.cache.Requests()
if !reflect.DeepEqual(requests, requestsWant) {
t.Errorf("%d: %v != %v", i, requests, requestsWant)
}

srgSpec, err := srgRec.SurrogateSpecification()
if err != nil {
t.Fatal(err)
}

requestsWant = []int{2, 2, 1}
requests = srgSpec.(*SrgSpecSMOKE).cache.Requests()
if !reflect.DeepEqual(requests, requestsWant) {
t.Errorf("%d: %v != %v", i, requests, requestsWant)
}
}
}
18 changes: 7 additions & 11 deletions emissions/aep/srgspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"encoding/csv"
"fmt"
"io"
"log"
"math"
"path/filepath"
"strconv"
Expand All @@ -32,7 +33,6 @@ import (
"github.com/ctessum/geom/encoding/shp"
"github.com/ctessum/geom/index/rtree"
"github.com/ctessum/requestcache"
"github.com/spatialmodel/inmap/internal/hash"
)

type SrgSpec interface {
Expand Down Expand Up @@ -78,10 +78,7 @@ type SrgSpecSMOKE struct {
// MergeMultipliers specifies multipliers associated with the surrogates
// in MergeNames.
MergeMultipliers []float64
}

type SrgSpecSMOKECache struct {
*SrgSpecSMOKE
cache *requestcache.Cache
}

Expand Down Expand Up @@ -216,11 +213,8 @@ func ReadSrgSpecSMOKE(fid io.Reader, shapefileDir string, checkShapefiles bool,
shpf.Close()
}
}
srgCache := &SrgSpecSMOKECache{
SrgSpecSMOKE: srg,
cache: newCache(srg.readSrgData, diskCachePath, memCacheSize, marshalSrgHolders, unmarshalSrgHolders),
}
srgs.Add(srgCache)
srg.cache = newCache(srg.readSrgData, diskCachePath, memCacheSize, marshalSrgHolders, unmarshalSrgHolders)
srgs.Add(srg)
}
return srgs, nil
}
Expand Down Expand Up @@ -260,6 +254,7 @@ func (srg *SrgSpecSMOKE) InputShapes() (map[string]*Location, error) {
inputData[inputID] = &Location{
Geom: ggeom,
SR: inputSR,
Name: srg.region().String() + inputID,
}
} else {
inputData[inputID].Geom = append(inputData[inputID].Geom.(geom.Polygon), ggeom...)
Expand All @@ -272,7 +267,7 @@ func (srg *SrgSpecSMOKE) InputShapes() (map[string]*Location, error) {
}

// get surrogate shapes and weights. tol is a geometry simplification tolerance.
func (srg *SrgSpecSMOKECache) getSrgData(gridData *GridDef, inputLoc *Location, tol float64) (*rtree.Rtree, error) {
func (srg *SrgSpecSMOKE) getSrgData(gridData *GridDef, inputLoc *Location, tol float64) (*rtree.Rtree, error) {
// Calculate the area of interest for our surrogate data.
inputShapeT, err := inputLoc.Reproject(gridData.SR)
if err != nil {
Expand All @@ -287,7 +282,7 @@ func (srg *SrgSpecSMOKECache) getSrgData(gridData *GridDef, inputLoc *Location,
}
}

key := fmt.Sprintf("smoke_srgdata_%s_%s_%g", hash.Hash(srg.SrgSpecSMOKE), hash.Hash(gridData.SR), tol)
key := fmt.Sprintf("smoke_srgdata_%s%s_%s_%g", srg.region(), srg.code(), gridData.SR.Name, tol)
request := srg.cache.NewRequest(context.TODO(), &readSrgDataInput{gridData: gridData, tol: tol}, key)
srgs, err := request.Result()
if err != nil {
Expand All @@ -308,6 +303,7 @@ func (srg *SrgSpecSMOKECache) getSrgData(gridData *GridDef, inputLoc *Location,
// surrogate definition, inputI is of type *osmReadSrgDataInput and
// inputI.tol is tolerance for geometry simplification.
func (srg *SrgSpecSMOKE) readSrgData(ctx context.Context, inputI interface{}) (interface{}, error) {
log.Printf("processing surrogate `%s` spatial data", srg.Name)
input := inputI.(*readSrgDataInput)

srgShp, err := shp.NewDecoder(srg.WEIGHTSHAPEFILE)
Expand Down
17 changes: 6 additions & 11 deletions emissions/aep/srgspec_osm.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"os"

"github.com/ctessum/geom"
"github.com/ctessum/geom/encoding/osm"
"github.com/ctessum/geom/index/rtree"
"github.com/ctessum/geom/proj"
"github.com/ctessum/requestcache"
"github.com/spatialmodel/inmap/internal/hash"
)

// SrgSpecOSM holds OpenStreetMap spatial surrogate specification information.
Expand All @@ -53,10 +53,7 @@ type SrgSpecOSM struct {
// MergeMultipliers specifies multipliers associated with the surrogates
// in MergeNames.
MergeMultipliers []float64 `json:"merge_multipliers"`
}

type srgSpecOSMCache struct {
*SrgSpecOSM
cache *requestcache.Cache
}

Expand All @@ -74,11 +71,8 @@ func ReadSrgSpecOSM(r io.Reader, diskCachePath string, memCacheSize int) (*SrgSp
}
srgs := NewSrgSpecs()
for _, s := range o {
sCache := &srgSpecOSMCache{
SrgSpecOSM: s,
cache: newCache(s.readSrgData, diskCachePath, memCacheSize, marshalSrgHolders, unmarshalSrgHolders),
}
srgs.Add(sCache)
s.cache = newCache(s.readSrgData, diskCachePath, memCacheSize, marshalSrgHolders, unmarshalSrgHolders)
srgs.Add(s)
}
return srgs, nil
}
Expand All @@ -92,7 +86,7 @@ func (srg *SrgSpecOSM) mergeMultipliers() []float64 { return srg.MergeMultipl

// getSrgData returns the spatial surrogate information for this
// surrogate definition and location, where tol is tolerance for geometry simplification.
func (srg *srgSpecOSMCache) getSrgData(gridData *GridDef, inputLoc *Location, tol float64) (*rtree.Rtree, error) {
func (srg *SrgSpecOSM) getSrgData(gridData *GridDef, inputLoc *Location, tol float64) (*rtree.Rtree, error) {
// Calculate the area of interest for our surrogate data.
inputShapeT, err := inputLoc.Reproject(gridData.SR)
if err != nil {
Expand All @@ -107,7 +101,7 @@ func (srg *srgSpecOSMCache) getSrgData(gridData *GridDef, inputLoc *Location, to
}
}

key := fmt.Sprintf("osm_srgdata_%s_%s_%g", hash.Hash(srg.SrgSpecOSM), hash.Hash(gridData.SR), tol)
key := fmt.Sprintf("osm_srgdata_%s%s_%s_%g", srg.region(), srg.code(), gridData.SR.Name, tol)
request := srg.cache.NewRequest(context.TODO(), &readSrgDataInput{gridData: gridData, tol: tol}, key)
srgs, err := request.Result()
if err != nil {
Expand All @@ -133,6 +127,7 @@ type readSrgDataInput struct {
// surrogate definition, inputI is of type *osmReadSrgDataInput and
// inputI.tol is tolerance for geometry simplification.
func (srg *SrgSpecOSM) readSrgData(ctx context.Context, inputI interface{}) (interface{}, error) {
log.Printf("processing surrogate `%s` spatial data", srg.Name)
input := inputI.(*readSrgDataInput)

srgSR, err := proj.Parse("+proj=longlat")
Expand Down
Loading

0 comments on commit 0e457f0

Please sign in to comment.