Django postgresql postgis incorrect spatial lookup - django

I have the following model:
class Item(Model):
lat_lng = PointField(geography=True, null=True)
Item.objects.create(lat_lng=Point(-95.864468, 36.075450))
bbox1 = (-168.3984375, 25.16517336866393, -52.03125, 75.32002523220804)
bbox2 = (-145.1953125, 25.16517336866393, -52.03125, 63.07486569058663)
bbox1 contains bbox2, but Item.objects.filter(lat_lng__coveredby=Polygon.from_bbox(bbox1)) doesn't return the item, while Item.objects.filter(lat_lng__coveredby=Polygon.from_bbox(bbox2)) returns it.
Am I missing something?
UPDATE:
If I remove geographic=True, then everything works. What does this flag stands for?

When using geography, great circle arcs are used instead of straight lines. This remains true for the lines connecting the bounding box corners.
The premise that box1 contains box2 is false. They may intersect, but one is not wholly contained in the other.
Box1 is wider than box 2, so its southern boundary, represented as a great circle arc, will go norther than box 2 boundary, and therefore the point is located south of box 1 but within box 2.

Related

How to change the bounding box thickness and label text in yolov5?

I am using YOLOv5s for object detection on custom datasets, there are multiple objects in given video, sometimes label text and bounding box thickness looks very bad. how can I customize these things?
when using detect.py, pass in the following arguments to adjust the labels and bounding boxes:
--line-thickness 1
--hide-labels True
--hide-conf True
For the --line-thickness argument, pass in an integer value to adjust the thickness, for labels and confidence, they are set to False by default. Setting them to True will hide them.
Be careful using --hide-labels True or hide-conf True. Under certain circumstances you can encounter an ErrorMessage. Only --hide-labels and --hide-conf should work perfectly fine.
Here is a list of arguments you can use with detect.py.
detect.py [-h] [--weights WEIGHTS [WEIGHTS ...]] [--source SOURCE]
[--data DATA] [--imgsz IMGSZ [IMGSZ ...]]
[--conf-thres CONF_THRES] [--iou-thres IOU_THRES]
[--max-det MAX_DET] [--device DEVICE] [--view-img]
[--save-txt] [--save-conf] [--save-crop] [--nosave]
[--classes CLASSES [CLASSES ...]] [--agnostic-nms]
[--augment] [--visualize] [--update] [--project PROJECT]
[--name NAME] [--exist-ok] [--line-thickness LINE_THICKNESS]
[--hide-labels] [--hide-conf] [--half] [--dnn]

Is there a way to have an if statement return the information of a cell?

I am making a camera check in/check out system. I have the person fill out a google form that is linked to a google sheet. This gives me what camera they checked out, their name, and the time checked out. I have another sheet that shows all of the data sorted. So, the camera if it checked in or out and the time it is checked out. Now I need to put the name next to the person that checked out the camera.
The way I have it set up you can check out multiple cameras at once so a simple LOOKUP won't work. I am trying to make an IF statement that looks at the date and time the camera was checked out and then goes into the google form linked sheet and looks for the date and time that is the same and then pastes the name, which is in the cell next to the date and time, in to the cell next to the camera in my other sheet.
This is what I have so far:
=IF(E2 = Data_Entered!A2:A, ,"Highlands")
I have it say Highlands if it is checked in Because the way I made the date was:
= If(C2= "Check Out", Now(), "Highlands")
So I don't need the name of the person when they check it in.
I want the IF statement to be like:
=IF(E2 = Data_Entered!A2:A,PASTE,"Highlands")
or something like that. As long as it works!
This is a link to a copy of the sheet:
https://docs.google.com/spreadsheets/d/1YbtxgI-Wp9nikDpKrLrpehNvQP3nRjNAWGPv2tMc5zg/edit?usp=sharing
delete everything in D:E range and paste this in D2 cell:
=ARRAYFORMULA(IF(LEN(A2:A), IF(C2:C= "Check Out", VLOOKUP(A2:A&"♦"&C2:C,
SORT(SPLIT(TRANSPOSE(SPLIT(TRIM(QUERY(TRANSPOSE(QUERY(TRANSPOSE(
IF((Data_Entered!E2:I<>"")*(Data_Entered!B2:B="Check Out"),
"♠"&Data_Entered!E2:I&"♦"&Data_Entered!B2:B&
"♣"&Data_Entered!D2:D&"♣"&Data_Entered!A2:A, ))
,,999^99)),,999^99)),"♠")), "♣"), 1, 0, 3, 0), {2, 3}, 0), "Highlands"), ))

igraph invalid vertex Id

I'm trying to run igraph's fast greedy community detection algorithm using the following code:
G = Graph()
L = []
V = []
for row in cr:
try:
l = []
source = int((row[0]).strip())
target = int((row[1]).strip())
weight = int((row[2]).strip())
l.append(source)
l.append(target)
if l not in L:
L.append(l)
if source not in V:
V.append(source)
if target not in V:
V.append(target)
except ValueError:
print "Value Error"
continue
if weight == 1:
continue
G.add_vertices(max(V))
G.add_edges(L)
cl = G.community_fastgreedy(weights=weight).as_clustering(10);
But this is the error I'm getting:
igraph._igraph.InternalError: Error at type_indexededgelist.c:272: cannot add edges, Invalid vertex id
I found this: Cannot add edges, Invalid vertex ID in IGraph so I tried adding all the vertices and then all the edges but I still get an error.
Does the above code do the same thing as:
tupleMapping = []
for row in cr:
if int(row[2]) < 10:
continue
l = [row[0], row[1], row[2]]
tupleMapping.append(tuple(l))
g = Graph.TupleList(tupleMapping)
cl = g.community_fastgreedy().as_clustering(20)
I dont have to explicitly say the G.community_fastgreedy(weights=weight) right?
Also another problem I was having; when I try to add more clusters in the following way:
cl = g.community_fastgreedy().as_clustering(10)
cl = g.community_fastgreedy().as_clustering(20)
I get two large clusters and the rest of the clusters compose of one element. This happens when I try to make the cluster size 5/10/20, is there any way for me to make the clusters more equally divided? I need more than 2 clusters for my dataset.
This is a small snippet of the data I'm trying to read from the csv file so that I can generate a graph and then run the community detection algorithm:
202,580,11
87,153,7
227,459,6
263,524,11
Thanks.
That's right, the second code does the same. In the first example, the problem is that when you add edges, you refer to igraph's internal vertex IDs, which always start from 0, and go until N-1. Does not matter your own vertex names are integers, you need to translate them to igraph vertex IDs.
The igraph.Graph.TupleList() method is much more convenient here. However, you need to specify that the third element of the tuple is the weight. You can do it either by weights = True or edge_attrs = ['weight'] arguments:
import igraph
data = '''1;2;34
1;3;41
1;4;87
2;4;12
4;5;22
5;6;33'''
L = set([])
for row in data.split('\n'):
row = row.split(';')
L.add(
(row[0].strip(), row[1].strip(), int(row[2].strip()))
)
G = igraph.Graph.TupleList(L, edge_attrs = ['weight'])
You can then create dictionaries to translate between igraph vertex IDs and your original names:
vid2name = dict(zip(xrange(G.vcount()), G.vs['name']))
name2vid = dict((name, vid) for vid, name in vid2name.iteritems())
However, the first is not so much needed, as you can always use G.vs[vid]['name'].
For fastgreedy, I think you should specify the weights, at least the documentation does not tell if it automatically considers the attribute named weight if such attribute exists.
fg = G.community_fastgreedy(weights = 'weight')
fg_clust_10 = fg.as_clustering(10)
fg_clust_20 = fg.as_clustering(20)
If fastgreedy gives you only 2 large clusters, I can only recommend to try other community detection methods. Actually you could try all of them which run within reasonable time (it depends on the size of your graph), and then compare their results. Also because you have a weighted graph, you could take a look at moduland method family, which is not implemented in igraph, but has good documentation, and you can set quite sophisticated settings.
Edit: The comments from OP suggest that the original data describes a directed graph. The fastgreedy algorithm is unable to consider directions, and gives error if called on a directed graph. That's why in my example I created an undirected igraph.Graph() object. If you want to run other methods, some of those might able to deal with directed networks, you should create first a directed graph:
G = igraph.Graph.TupleList(L, directed = True, edge_attrs = ['weight'])
G.is_directed()
# returns True
To run fastgreedy, convert the graph to undirected. As you have a weight attribute for the edges, you need to specify what igraph should do when 2 edges of opposit direction between the same pair of vertices being collapsed to one undirected edge. You can do many things with the weights, like taking the mean, the larger, or the smaller one, etc. For example, to make the combined edges have a mean weight of the original edges:
uG = G.as_undirected(combine_edges = 'mean')
fg = uG.community_fastgreedy(weights = 'weight')
Important: be aware that at this operation, and also when you add or remove vertices or edges, igraph reindexes the vertices and edges, so if you know that vertex id x corresponds to your original id y, after reindexing this won't be valid anymore, you need to recreate the name2vid and vid2name dictionaries.

Remove blanks at ends of DataVisualization chart x axis

I am using Microsoft's DataVisualization.Charting.Chart, and I have integer values along the X axis, using line-style graphs. However, the chart is adding an extra blank item at the beginning and end of the x-axis, with no value labels to explain what they are.
How can I remove these empty items and make the lines go right up to the ends?
Use the IsMarginVisible property of the xaxis. I believe that will do the trick.
To test this, I changed one of my own charts to be a line chart and then set the value in the code:
ReactivityChart.ChartAreas(0).AxisX.IsMarginVisible = False
Tell me if this is what you were hoping to get or if I have totally misunderstood the question:
(note that I do not have a high enough rep to post this image)
http://www.rectorsquid.com/chartmargintest.gif
You should set the Maximum and Minimum properties in ChartArea.AxisX, e.g. :
this.chart1.ChartAreas[0].AxisX.Minimum = 0; // if your minimum X = 0
this.chart1.ChartAreas[0].AxisX.Maximum = 100; // if your maximum X = 100
In this way, your chart area will show only the values between Minimum and Maximum.

How do I supply a British National Grid reference as WKT to GeoDjango?

I'm trying to insert some National Grid references into a Django PointField defined as follows:
oscode = models.PointField(srid=27700, null=True, blank=True)
However, I don't know how to format them correctly in WKT. This is what I get if I try simply using a basic National Grid reference, TR3241:
INSERT INTO places (placeid, structidx, subidx, county, name, oscode) VALUES ('10', '1', '1', 'Kent', 'Dover', 'TR3241');
psycopg2.InternalError: parse error - invalid geometry
LINE 1: ...'1', 'Kent', 'D1', 'Eastry', 'Bewsbury', 'Dover', 'TR3241', ...
^
HINT: You must specify a valid OGC WKT geometry type such as POINT, LINESTRING or POLYGON
And this is what I get if I (guessing wildly after reading up on WKT!) use POINT(TR3241):
psycopg2.InternalError: parse error - invalid geometry
LINE 1: ...'1', 'Kent', 'D1', 'Eastry', 'Bewsbury', 'Dover', 'POINT(TR3...
^
HINT: "POINT(" <-- parse error at position 6 within geometry
How do I format the grid ref correctly?
You would just need something like this, assuming a point with lon1 lat1:
insert into geography_table (name, geometry_field) values ('Chez Francois',\
ST_GeomFromText('POINT(lon1 lat1)', 27700));
It looks like your geometry column is called oscode; to check use psql mydb and hit \d. You should see a list of all tables, the one(s) you are interested in will be listed as type geometry. There should be a line at the bottom something like "enforce_srid_oscode" CHECK (st_srid(oscode) = 27700).
The big picture bit that may be throwing you off is that these records are just regular database tables, with at least one column containing details about some geometry on Earth. The inserts on these geometric values must be geometric types, and the way you get from (relatively) plain English to these geometries is with a geometry constructor.