Django loaddata: YAML fixtures + GeoDjango MultiPolygon - django

I am producing a fixture set using pyyaml (among other libraries) which I want to load into my django project with manage.py loaddata. Something is not working with the YAML I am producing (or with GeoDjango, or something else, I suppose) when I run loaddata.
I get this error: Cannot set Neighborhood GeometryProxy (MULTIPOLYGON) with value of type: <type 'list'>
This is a sample of the data I'm trying to load. Below it is the model definition
- fields:
external_id: unincorporated-catalina-island
name: Unincorporated Catalina Island
region: 5
shape:
- - - [-118.604432, 33.47871]
....
- [-118.604375, 33.478642]
- [-118.604325, 33.478558]
- [-118.603603, 33.47794]
model: geo.neighborhood
model:
from django.db import models
from django.contrib.gis.db import models as geo_models
class Area(ABase):
"""
An area defines a geographic area of any size. This abstract class is
subclassed in order to define the type of area being modeled, e.g.
a wide region or a smaller neighborhood.
"""
name = models.CharField(max_length=200)
external_id = models.CharField(max_length=200, blank=True, unique=True,
help_text="The ID of this area in a third party datasource")
shape = geo_models.MultiPolygonField()
def __unicode__(self):
return self.name
class Meta(ABase.Meta):
abstract = True
ordering = ['name']
I presume I'm not formatting the shape field correctly.
The JSON source is here:
I then tried giving the YAML file the whole geometry dict, as below:
- fields:
external_id: lake-los-angeles
name: Lake Los Angeles
region: 2
shape:
coordinates:
- - - [-117.845055, 34.631392]
...
- [-117.845055, 34.631392]
type: MultiPolygon
model: geo.neighborhood
But this produces pretty much the same error as above:
Cannot set Neighborhood GeometryProxy (MULTIPOLYGON) with value of type: <type 'dict'>
to continue the process, I tried the most minimal, hand-crafted version of the YAML file (edited here for brevity by removing a big chunk of the middle coordinates):
- {model: geo.region, fields: {province: 1, id: &angeles-forest 1,
name: Angeles Forest, external_id: angeles-forest, shape: [ [ [ [ -118.298947, 34.157699 ], [ -118.298830, 34.157683 ], [ -118.298638, 34.157808 ], [ -118.298481, 34.157914 ], [ -118.298172, 34.158122 ], [ -118.297935, 34.158293 ], [ -118.297878, 34.158342 ], [ -118.297854, 34.158477 ], [ -118.297837, 34.158577 ], [ -118.297744, 34.158575 ], [ -118.299082, 34.157728 ], [ -118.298947, 34.157699 ] ] ] ]}}
This produces the same error as above, complaining about <type 'list'>
What should the YAML file's multipolygon (here, 'shape') field look like for loaddata to accept it?

GEOS is looking for WKT (Well Known Text) format, which is close to, but not the same as, the geoJSON/YAML format above.
The practical solution was to use geomet to transform the JSON input into WKT, which could then comfortably reside within the YAML file... fun with brackets varieties!
So then the successful format looks like this:
- fields: {external_id: toluca-lake, name: Toluca Lake, region: 9, shape: 'MULTIPOLYGON
(((-118.357158 34.164806, -118.357154 34.163097, -118.357151 34.161287, -118.356036
34.161287, -118.354978 34.161288, -118.354682 34.161288, -118.354020 34.161288,
-118.353103 34.161289, -118.353034 34.161128, -118.352925 34.160873, -118.352156
34.159076, -118.352138 34.159033, -118.351812 34.158271, -118.351554 34.157668,
-118.351235 34.156925, -118.350751 34.155794, -118.350196 34.154497, -118.349988
34.154012, -118.349958 34.153941, -118.349830 34.153812, -118.349756 34.153629,
-118.349673 34.153425, -118.349643 34.153350, -118.349664 34.153256, -118.349216
34.152209, -118.348450 34.150419, -118.348067 34.149523, -118.347680 34.148618,
-118.347555 34.148327, -118.347308 34.147748, -118.346800 34.146562, -118.346767
34.146485, -118.346624 34.146151, -118.346446 34.145735, -118.346430 34.145696,
-118.345949 34.144573, -118.345903 34.144218, -118.345691 34.142572, -118.345678
34.142466, -118.345665 34.142367, -118.345665 34.142367, -118.345698 34.142356,
-118.346425 34.142207, -118.346907 34.142174, -118.347168 34.142177, -118.347168
34.142177, -118.347522 34.142180, -118.348435 34.142262, -118.351608 34.142887,
-118.352051 34.142964, -118.354160 34.143211, -118.354603 34.143227, -118.357641
34.143337, -118.357783 34.143342, -118.357967 34.143348, -118.358339 34.143269,
-118.358930 34.143143, -118.359082 34.143111, -118.359198 34.143088, -118.361136
34.142712, -118.361258 34.142688, -118.361267 34.142686, -118.361264 34.142680,
-118.361340 34.142669, -118.361411 34.142907, -118.361711 34.143307, -118.362211
34.144107, -118.362911 34.145107, -118.363350 34.145900, -118.363863 34.146805,
-118.364611 34.148106, -118.365011 34.148806, -118.365312 34.149206, -118.365512
34.149606, -118.366012 34.150406, -118.366612 34.151206, -118.367112 34.152206,
-118.367609 34.153023, -118.367885 34.153506, -118.368500 34.154522, -118.368612
34.154706, -118.369145 34.155691, -118.369652 34.156644, -118.370237 34.157613,
-118.369112 34.157606, -118.368112 34.157606, -118.367012 34.157606, -118.365929
34.157604, -118.364912 34.157606, -118.363793 34.157613, -118.362712 34.157606,
-118.361601 34.157613, -118.361623 34.159427, -118.361612 34.161206, -118.361612
34.163106, -118.361612 34.164806, -118.360512 34.164806, -118.359412 34.164806,
-118.358211 34.164806, -118.357211 34.164806, -118.357158 34.164806)))'}
model: geo.neighborhood

Related

How to match AmChart GeoJson data using string

I'm trying to plot some counts per State county using AmCharts and their GeoJson file. For example, loading FL counties and adding the counts. However, it seems I need to know the ID of the county, and not just the name. Is there a way to match the GeoJson using the county name?
I tried the simple idea of accessing the properties "name" in the GeoJson data and adding the count in polygonSeries.data but that doesn't work. It only works when providing the id.
When adding data, AmCharts allows something like this
polygonSeries.data =[
{ id: "12133", value: 60.524 }, // Washington
{ id: "12131", value: 300 }, // Walton
{ id: "12129", value: 500 }, // Wakulla
];
The above works. The below doesn't
polygonSeries.data = [
{ name: "Washington", value: 60.524 }, // Washington
{ name: "Walton", value: 300 }, // Walton
{ name: "Wakulla", value: 500 }, // Wakulla
];
The GeoJson data contains the relevant information like this
properties:{name:"Washington",id:"12133",STATE:"FL",TYPE:"County",CNTRY:"USA"},id:"12133"}
It apparently is matching the properties.id to find the object and that's why it works with the ids. However, that means I would need to know the ID for every county to begin with.
So is there a way to match using the county name instead?
I would expect AmCharts to match the relevant properties and not just the ID since those are relatively unknown to people.
After speaking to amChart support, it's not possible to do this.

Elixir: ExAws: DynamoDB: query-filter

I'm using the library https://github.com/ex-aws/ex_aws_dynamo, and I'm having issues getting a working example of query-filter to work with query. I was hoping someone here has an example they could share.
Here's what I've tried, but it returns an error:
[
key_condition_expression: "highlight_request_id = :highlight_request_id",
expression_attribute_values: [
highlight_request_id: "c692e65e-618f-45a3-ac12-d8103e6444c8"
],
query_filter: %{
range_id: %{
attribute_value_list: ["9990-ORGANIZATION-Pampers"],
comparison_operator: "EQ"
}
}
]
and the error I get back:
{:error,
{"ValidationException",
"1 validation error detected: Value null at 'queryFilter.range_id.member.comparisonOperator' failed to satisfy constraint: Member must not be null"}}
I'm not sure what is considered to be null. Any thoughts?
Make sure your query is written like so (adapted from the ex_aws_dynamo tests):
ExAws.Dynamo.query("person", [
index_name: "email",
key_condition_expression: "#email = :email",
expression_attribute_names: %{"#email" => "email"},
expression_attribute_values: [email: "person#test.com", last_name: "Person"],
filter_expression: "last_name = :last_name"
]) |> ExAws.request()
I was able to run this successfully against my local table, you'll have to fill in the appropriate values for your model. In particular, you'll want to include the index_name, and use the filter_expression, rather than query_filter.
In your case, I believe you'd want something like
ExAws.Dynamo.query("person", [
index_name: "highlight_request_id", # assuming that's the name of the index
key_condition_expression: "#highlight_request_id = :highlight_request_id",
expression_attribute_names: %{"#highlight_request_id" => "highlight_request_id"},
expression_attribute_values: [highlight_request_id: "c692e65e-618f-45a3-ac12-d8103e6444c8", range_id: "9990-ORGANIZATION-Pampers"],
filter_expression: "range_id = :range_id"
]) |> ExAws.request()
Let me know if this gets you any closer - again, worked for me, using the latest version of ex_aws_dynamo (2.2.2, at the moment).

How to load RubyMotion table view cell data from file

I'm getting started with RubyMotion and ProMotion. I'm building a table view and I would like to move the data out into an external file to make it easier to manage. Here's what I have so far:
class MasterScreen < PM::TableScreen
title 'States'
def table_data
[{
title: "Northwest States",
cells: [
{ title: "Oregon", action: :view_details, arguments: { state: #oregon }},
{ title: "Washington", action: :view_details, arguments: { state: #washington }}
]
}]
end
def view_details
open DetailScreen.new(nav_bar: true)
end
end
I'd like to move the names of the states (basically the cell titles) into something like a YAML or JSON file that I can load and iterate over. How can I achieve something like this?
Update: I managed to figure out how to load text from a file.
First I added bubble-wrap to my Gemfile and ran bundle install. BubbleWrap provides the helper method App.resources_path.
In my_app/resources/states.txt I have a list of states, separated by new lines:
Oregon
Washington
Foobar
In my Table View Controller, I read the file and split the file into an array of lines.
class MasterScreen < PM::TableScreen
title 'States'
def on_load
data = File.read("#{App.resources_path}/states.txt")
#states = data.lines
end
def table_data
[{
title: "Northwest States",
cells: #states.map do |state|
{
title: state,
action: :view_details,
arguments: { state: state }
}
end
}]
end
def view_details(arguments)
open DetailScreen.new(nav_bar: true, title: arguments[:state])
end
end
This works, but it's only part of what I was trying to do. I would still like to use a structure like YAML to represent titles and subtitles. What would be the RubyMotion way to do this sort of thing?
Figured out how to do it. I came across a RubyMotion gem called motion-yaml. Simply add it to your Gemfile, add your YAML file to your resources directory, and use it like you would YAML in Ruby.
data = YAML.load(File.read("#{App.resources_path}/my_yaml_file.yml"))
Note: You will need to add bubble-wrap to your Gemfile in order to have the App.resources_path. I'm not sure if there is an easy way to do it without bubble-wrap.

How to Populate koGrid Groups Array

I have a koGrid configured as follows:
var myItemsGrid = {
data: myItems,
columnDefs: [
{ field: 'item.title', displayName: 'Title', cellTemplate: $("#cdfUrlCellTemplate").html() },
{ field: 'item.dueTimeUtc', displayName: 'Due', cellFormatter: formatDate, sortFn: sortDates },
{ field: 'id', displayName: 'Edit', cellTemplate: $("#editCellTemplate").html() }
],
showGroupPanel: true,
groups: ['item.title'],
showFilter: false,
canSelectRows: false
};
My problem is that the groups array, which I have tried to populate using the field name of one of the fields in my grid, causes the following error:
TypeError: Cannot read property 'isAggCol' of undefined
How should I be populating the groups array so that I can set up initial grouping for my grid?
I had the same problem and took a different approach by sending an event to the grid control to group by the first heading. Something like this:
jQuery("#symbolPickerView").find(".kgGroupIcon").first().click();
This works until there is some sort of patch generally available.
I ended up having to patch the koGrid script to get the initial grouping of columns to work.
If anyone else has the problem I'm happy to provide the patched script. I will look at making a pull request to get the fix into the koGrid repository after putting it through its paces a bit more.

Problems combining (union) Multipolygons in geodjango

I'm using geodjango and postgis (1.x),
What is the best way to combine (union) a list of multipolygons.
in what i assume is rather inefficient i'm looping trough like this
combined = multipolygon
for item in items:
combined = combined.union(item.geom) #geom is a multipolygon
Usually this works fine, but often i'm getting the error Error encountered checking Geometry returned from GEOS C function "GEOSUnion_r".
Here is the geo json version of the item the error is thrown on if it helps
{ "type": "MultiPolygon", "coordinates":
[ [ [ [ -80.077576, 26.572225 ],
[ -80.037729, 26.571180 ],
[ -80.080279, 26.273744 ],
[ -80.147464, 26.310066 ],
[ -80.152851, 26.455851 ],
[ -80.138560, 26.538013 ],
[ -80.077576, 26.572225 ]
] ] ]
}
does anyone have anyideas? the end goal is to take find all the locations (another table) which fall within this list of n polygons (using coordinates__within=combined_area)
Also, the polygons show up fine on the maps in the geodjango admin.
You can always use Union aggregate method. That should be a bit more efficient because everything is computed on the database level which means you don't have to loop over things in Python.
combined_area = FooModel.objects.filter(...).aggregate(area=Union('geom'))['area']
final = BarModel.objects.filter(coordinates__within=combined_area)