Expanded example using distance() function - orientdb

Note, I'm aware of OrientDB geolocation (though I have some trouble with the poor formatting of the accepted answer, as it makes huge assumptions and in fact may be syntactically incorrect, but cannot yet submit edits).
I have a Vertex of Bank with a property of latLong as a comma-delimited string. I'm having some trouble using the provided distance() function with OrientDB. Since distance(x,y,lat,long) is expecting discrete values we wrote a split function that returns the latLong as an array:
{ ..., values: [xx.xxx,yy.yyy], ... }
However, I (we) can't seem to make either the provided answer or the document example to work. I suspect the answer is simple and we're over thinking it, but we're stuck.
split(input,delimiter)
return input.split(delimiter)`
Pretty simple really.
What's wrong in the original question?
In the cited question above, the query
select distance(x,y,originx,originy) <= 30 as distance from Bank order by distance
generates the below error
com.orientechnologies.orient.core.sql.OCommandSQLParsingException: Error on parsing command at position #0: Error parsing query: select distance(x,y,originx,originy) <= 30 as distance from Bank Encountered " "<=" "<= ""
and should be
select distance(x,y,lat,long) as distance from Bank where distance <= 30 order by distance;
which returns nothing.
If Bank were to have discrete properties for lat and long, how are they passed to distance()? Specifically, is OrientDB expecting specific property names?

You have to insert in Bank the properties lat and long like double

Related

Smartsheet function is UNPARSEABLE

On the Sheet Summary I'm trying to write a function that will track Past Due tasks below is the format :
=COUNTIF([Is Past Due?]:[Is Past Due?], "Yes")
The formula doesn't work as it says "UNPARSEABLE". Below is the Past Due column name
The UNPARSEABLE error in Smartsheet happens when, the formula has a problem which prevents it from being parsed and interpreted.
Example:
-misspelling
-incomplete operators
-using the wrong case for a column name
-using single quotes instead of double quotes
Maybe, you have to review the syntax of the function COUNTIF, and make sure to use acceptable operators, follow this link for more information about the function
---Syntax---
COUNTIF( range,criterion )
range
— The group of cells to count.
criterion
— The value that determines which cells in the range will be counted.
I hope this information can be useful for you.

Cannot properly array googlefinance formula with dates

I am trying to convert money amounts in USD to EUR, but I want to do it in relation to date of transaction taking place due to dyncamic exchange rates.
Idea is to use googlefinance function with index function, along with date function, which will be made of right, mid, and left functions. All of that should be wrapped with arrayformula. Numbers should be rounded using round.
Non-working example:
Don't mind ;, this is instead of , in my google sheets language settings.
Formula: =ARRAYFORMULA(IF(B2:B="";"";ROUND(INDEX(B2:B*GOOGLEFINANCE("CURRENCY:USDEUR";"price";DATE(RIGHT(A2:A;4);MID(A2:A;4;2);LEFT(A2:A;2)));2;2);2)))
Formula (with , instead of ;):
=ARRAYFORMULA(IF(B2:B="","",ROUND(INDEX(B2:B*GOOGLEFINANCE("CURRENCY:USDEUR","price",DATE(RIGHT(A2:A,4),MID(A2:A,4,2),LEFT(A2:A,2))),2,2),2)))
Since I'm pretty sure this formula should work in "normal circumstances", I've replicated it leaving out arrayformula, and full ranges (such as B2:B, etc), and it works once I drag down the formula.
Working example:
Formula: =IF(F2="";"";ROUND(INDEX(F2*GOOGLEFINANCE("CURRENCY:USDEUR";"price";DATE(RIGHT(E2;4);MID(E2;4;2);LEFT(E2;2)));2;2);2))
Formula (with , instead of ;):
=IF(F2="","",ROUND(INDEX(F2*GOOGLEFINANCE("CURRENCY:USDEUR","price",DATE(RIGHT(E2,4),MID(E2,4,2),LEFT(E2,2))),2,2),2))
Does anyone have idea what's going on with the first case, i.e. why it doesn't work? I believe it has to be something with those full ranges (e.g. B2:B, A2:B, etc), but not sure why...
GOOGLEFINANCE is already an ARRAYFORMULA type formula so try like this:
=ARRAYFORMULA(IF(B2:B="";;ROUND(B2:B*IFNA(VLOOKUP(A2:A+0,9986111111;
GOOGLEFINANCE("CURRENCY:USDEUR"; "price"; MIN(A2:A); MAX(A2:A)+1); 2; 1)); 2)))

qPython QProjection Issues instead of queried data

I tried writing a Q Code which will allow me to pass parameters however I am getting a results as Qprojection. I tried using
qpython.sync() is returning a QProjection instead of the queried data
but solution isn't working(new to Q/kdb world)
Any ideas on what exactly I should change?
q.sync(
'''{[x;y;z]select from quotestackevent where date within(x;y),sym=z}''',
[np.datetime64('2018-04-14','D'), #start date
np.datetime64('2018-04-14','D'), #end date
np.string_('GBPUSD')])
In Q/KDB the functional format is {......}[x;y;z], with x y z being the arguments. If you have left a blank argument then the function becomes a projection.
qpython allows you to pass python arguments to a q function, with the format being q.sync('{......}',x,y,z).
In your example the square brackets is causing the inputs to be passed as a single array to the function, resulting in a projection. This can be fixed by removing the square bracket.
q.sync('{[x;y;z]select from quotestackevent where date within(x;y),sym=z}', np.datetime64('2018-04-14','D'), np.datetime64('2018-04-14','D'), np.string_('GBPUSD'))
Hope this helps!

set threshold as a function of autoThreshold

I have written a macro for ImageJ/FIJI to deconvolve my confocal microscopy images and run the "3D Object Counter" plugin. The macro successfully runs all required commands and saves all required data in the specified places.
However, I have found that the 3D-OC autothreshold (as shown in the plugin dialog box) is to stringent resulting in objects being lost or divided.
To remedy this I would like to reduce the autothreshold by a predetermined function something similar to what was done here (from:How to get threshold value used by auto threshold Plugin) which resulted in this code:
setAutoThreshold();
getThreshold(lower,upper);
v=setThreshold(lower,upper*0.5);
run("3D Objects Counter", "threshold="v" slice=10 min.=400 max.=20971520 objects statistics summary");
The idea was to call the AutoThreshold values, modify them and set them to a variable. However when these lines are run the following error is returned:
Number or numeric function expected in line 3.
v=<setThreshold>(lower,upper*0.5);
And if the variable is inserted directly into the threshold key for run(3D-OC) the following msg is encountered:
Numeric value expected in run() function
Key:"threshold"
Value or variable name:"setThreshold(lower,upper*0.5"
Any suggestions or help on how to designate the 3D-OC threshold value as a variable as described would be greatly appreciated (as would any work arounds of course :) ).
Cheers
Edit: After testing Jan's response below (which works perfectly), it appears I need to call the threshold set by the 3D-OC plugin. Anyone know how to do this?
The getThreshold(lower, upper) function returns the lower and upper threshold levels in the provided variables. There is no need to assign any value to a new variable, and as you observed, setThreshold does not have any return value.
Instead, you can use the value(s) returned from getThreshold and use them as parameters in the run method (in the correct way, by string concatenation, see here):
setAutoThreshold();
getThreshold(lower, v);
run("3D Objects Counter", "threshold=" + v + " slice=10 min.=400 max.=20971520 objects statistics summary");
Alternatively, you can use &v in the second parameter to avoid string concatenation in the last line (see the documentation for the run() macro function):
run("3D Objects Counter", "threshold=&v slice=10 min.=400 max.=20971520 objects statistics summary");
You might have to use the lower instead of the upper threshold value, depending on whether you count bright or dark objects.

How to add a method in DataMapper so I can find "all points within x distance of this latitude and longitude"?

I'm using DataMapper to manage a database that has points of interest (POIs) located by latitude and longitude. I would like to do a query and find all POIs within x distance of a given latitude and longitude. For example, all POIs within 1000m of latitude 45, longitude 90.
I set this up:
class POI
include DataMapper::Resource
property :id, String, :key => true
property :title, String, :required => true
property :lat, Float, :required => true
property :lon, Float, :required => true
def distance(latitude, longitude)
# Taken from https://github.com/almartin/Ruby-Haversine
earthRadius = 6371 # Earth's radius in km
# convert degrees to radians
def convDegRad(value)
unless value.nil? or value == 0
value = (value/180) * Math::PI
end
return value
end
deltaLat = (self.lat - latitude)
deltaLon = (self.lon - longitude)
deltaLat = convDegRad(deltaLat)
deltaLon = convDegRad(deltaLon)
# Calculate square of half the chord length between latitude and longitude
a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
Math.cos((self.lat/180 * Math::PI)) * Math.cos((latitude/180 * Math::PI)) *
Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
# Calculate the angular distance in radians
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
distance = earthRadius * c
return distance
end
end
I'd like to be able to find records with a call similar to this:
pois = POI.all(distance(45,90).lte => 1000)
But that gives an error:
./poi-provider.rb:44:in `<main>': undefined method `distance' for main:Object (NoMethodError)
I read dkubb's answer about defining complex queries in a method but this is different because I need to pass parameters in and I'm trying to use the method as a condition.
How can I do that---or, is there a better way to use DataMapper to find points near a given latitude and longitude without breaking down and just using raw SQL?
Whenever you're dealing with latitudes and longitudes, I would very strongly recommend that you use a spatial database rather than just two Float columns. Otherwise your queries will become crazily slow as soon as you have more than a trivial quantity of data.
MySQL does have spatial extensions, but the de facto standard for open-source spatial databases is the PostGIS extension to Postgres. Fortunately, you can use this with DataMapper fairly easily.
Installing
You'll need the dm-postgis plugin. The main code appears to be abandonware, but someone has updated it to work with current DataMapper. Clone dm-postgis from github, apply this pull request, and then gem install from the local directory.
You'll also find life easier if you install dm-ar-finders, which lets you use SQL queries and get DataMapper objects back.
Data model
You can then define your co-ordinate property as a PostGIS geometry type like this:
property :location, PostGISGeometry
and set it this way:
location=GeoRuby::SimpleFeatures::Point.from_x_y(longitude,latitude)
You'll probably want to create an index on your location column. Rather than Postgres's default B-tree, you want a GIST index for geographic data. dm-postgis unfortunately isn't smart enough to create this, so do it from the psql command line:
CREATE INDEX index_poi_location ON poi USING GIST (location);
The proximity query
Ok. So now you have a location field. How do you run your proximity query?
The key is PostGIS's ST_DWithin function. As the docs say, this "returns true if the geometries are within the specified distance of one another". So in your case, you'd do something like this:
POI.find_by_sql "SELECT id,name FROM pois WHERE ST_DWithin(location, ST_GeomFromText('POINT(45 90)') , 0.05 )"
The 0.05 is the distance required. Note that this is in degrees, not metres. (Talking about projections and SRIDs is way beyond the scope of this answer, but if, for example, all your data was in the UK, you could use the OSGB projection and get metres pretty easily. Alternatively, someone could improve dm-postgis to cope with PostGIS geographies as well as geometries, which cope with metre distances natively. It's on my list... one day.)
The really great thing about all this is that PostGIS puts much more complex geographical queries within your grasp. For example, in a project I'm currently working on, I'm using it like this:
shops=Shop.find_by_sql [<<-EOS,route.id]
SELECT listings.id, listings.name, listings.provides
FROM listings
JOIN routes ON ST_DWithin(listings.location, routes.linestring, 0.05)
WHERE routes.id=? AND type='Shop'
ORDER BY ST_Line_Locate_Point(routes.linestring, listings.location)
EOS
That finds all the shops along a particular route (a polyline) and orders them start-to-finish... and does it remarkably quickly.
You're calling an instance method without instantiating. That's what is causing your error.
You can't use DataMapper methods as conditions. This means you're going to have to write some SQL.
Something like:
class POI
...
def self.all_within_distance(distance, longitude, latitude)
repository.adapter.query "SELECT *
FROM pois
WHERE " + distance.to_s + " > ** Complicated math coded in SQL that gets uses poi.lon and poi.lat to get the distance from the given longitude and latitude ** "
end
Then call
POI.all_within_distance(1000, 45, 90)