forked from spatialmodel/inmap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
save.go
120 lines (104 loc) · 3.24 KB
/
save.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
Copyright © 2013 the InMAP authors.
This file is part of InMAP.
InMAP is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
InMAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with InMAP. If not, see <http://www.gnu.org/licenses/>.
*/
package inmap
import (
"encoding/gob"
"fmt"
"io"
"sort"
"github.com/ctessum/geom"
)
func init() {
gob.Register(geom.Polygon{})
gob.Register(geom.MultiPolygon{})
gob.Register(&geom.Bounds{})
gob.Register(geom.Point{})
gob.Register(geom.MultiPoint{})
gob.Register(geom.LineString{})
gob.Register(geom.MultiLineString{})
}
type versionCells struct {
// DataVersion holds the variable grid data version of the software
// that saved this data, if any, and should match the VarGridDataVersion
// global variable.
DataVersion string
Cells []*Cell
}
// Save returns a function that saves the data in d to a gob file
// (format description at https://golang.org/pkg/encoding/gob/).
func Save(w io.Writer) DomainManipulator {
return func(d *InMAP) error {
if d.cells.len() == 0 {
return fmt.Errorf("inmap.InMAP.Save: no grid cells to save")
}
// Set the data version so it can be checked when the data is loaded.
data := versionCells{
DataVersion: VarGridDataVersion,
Cells: d.cells.array(),
}
e := gob.NewEncoder(w)
if err := e.Encode(data); err != nil {
return fmt.Errorf("inmap.InMAP.Save: %v", err)
}
return nil
}
}
// Load returns a function that loads the data from a previously Saved file
// into an InMAP object.
func Load(r io.Reader, config *VarGridConfig, emis *Emissions, m Mechanism) DomainManipulator {
return func(d *InMAP) error {
dec := gob.NewDecoder(r)
var data versionCells
if err := dec.Decode(&data); err != nil {
return fmt.Errorf("inmap.InMAP.Load: %v", err)
}
if err := d.initFromCells(data.Cells, emis, config, m); err != nil {
return err
}
if data.DataVersion != VarGridDataVersion {
return fmt.Errorf("InMAP variable grid data version %s is not compatible with "+
"the required version %s", data.DataVersion, VarGridDataVersion)
}
return nil
}
}
func (d *InMAP) initFromCells(cells []*Cell, emis *Emissions, config *VarGridConfig, m Mechanism) error {
d.init()
// Create a list of array indices for each population type.
d.PopIndices = make(map[string]int)
for i, p := range config.CensusPopColumns {
d.PopIndices[p] = i
}
d.mortIndices = make(map[string]int)
mortRateColumns := make([]string, len(config.MortalityRateColumns))
i := 0
for m := range config.MortalityRateColumns {
mortRateColumns[i] = m
i++
}
sort.Strings(mortRateColumns)
for i, m := range mortRateColumns {
d.mortIndices[m] = i
}
for _, c := range cells {
d.InsertCell(c, m)
}
// Add emissions to new cells.
// This needs to be called after setNeighbors.
if err := d.SetEmissionsFlux(emis, m); err != nil {
return err
}
return nil
}