Related
I am trying to calculate SAVI vegetation index using MODIS data. But I am getting an error showing:
Image.select: Pattern 'B2' did not match any bands.
Code:
countries = ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017")
canada = countries.filter(ee.Filter.eq("country_na", "Canada"))
image = ee.ImageCollection("MODIS/061/MOD09A1")\
.filterDate('2017-01-01','2017-12-31')\
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10))\
.filterBounds(canada)\
.median()\
.clip(canada)
savi = image.expression(
'1.5*((NIR-RED)/(NIR+RED+0.5))',{
'NIR':image.select('B2'),
'RED':image.select('B1')
}).rename('savi')
saviVis = {'min':0.0, 'max':1, 'palette':['yellow', 'green']}
Map = geemap.Map()
Map.addLayer(savi, saviVis, 'SAVI')
Map
Why am I getting this error? Isn't B1 designated to Red and B2 to NIR?
The general thing to do when you hit this type of problem is to start examining the dataset for what is actually there — how many images are you matching, what properties and bands those images have, etc. I found two problems:
Your filter criteria matched zero images. Therefore the collection is empty, and therefore the median() image from that collection has no bands at all. (You can check this by putting the collection in a variable and printing the size() of it.) You will need to adjust the criteria.
It seems that the main reason they didn't match is that the images in MODIS/061/MOD09A1 do not have a CLOUDY_PIXEL_PERCENTAGE property.
The band names for MODIS/061/MOD09A1 are not B1, B2, ... but sur_refl_b01, sur_refl_b02 and so on. You can see this with the Inspector in the Earth Engine Code Editor, or on the dataset description page.
Perhaps you were working from information about a different dataset?
With the two problems above fixed, your code produces some results. This is the (JS) version I produced while testing (Code Editor link):
var countries = ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017");
var canada = countries.filter(ee.Filter.eq("country_na", "Canada"));
var images = ee.ImageCollection("MODIS/061/MOD09A1")
.filterDate('2017-01-01','2017-12-31')
// .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10))
.filterBounds(canada);
// print(images);
var image = images.median().clip(canada);
Map.addLayer(canada);
Map.addLayer(image);
var savi = image.expression(
'1.5*((NIR-RED)/(NIR+RED+0.5))',{
'NIR':image.select('sur_refl_b02'),
'RED':image.select('sur_refl_b01')
}).rename('savi');
var saviVis = {'min':0.0, 'max':1, 'palette':['yellow', 'green']};
Map.addLayer(savi, saviVis, 'SAVI')
The "Road Shape and Road Class Filters" resource's example seems to imply that CF data is mapped to the current shape. This is because CF and SHP tags are siblings.
<?xml version="1.0" encoding="UTF-8"?>
<TRAFFICML_REALTIME CREATED_TIMESTAMP="2017-06-02T18:10:48Z" MAP_VERSION="" UNITS="imperial" VERSION="3.2" xmlns="http://traffic.nokia.com/trafficml-flow-3.2">
<RWS EBU_COUNTRY_CODE="1" EXTENDED_COUNTRY_CODE="A0" MAP_VERSION="201702" TABLE_ID="7" TY="TMC" UNITS="imperial">
<RW DE="Binford Blvd" LI="107+01100" PBT="2017-06-02T18:10:13Z" mid="1fe417f0-f17e-47b8-b0b0-b67a71eec11d|">
<FIS>
<FI>
<TMC DE="E Kessler Boulevard East Dr" LE="1.5983" PC="8367" QD="-"/>
<SHP FC="3">39.8405,-86.11263 39.84072,-86.11237</SHP>
<SHP FC="3">39.84072,-86.11237 39.8413,-86.11168</SHP>
<SHP FC="3">39.8413,-86.11168 39.84181,-86.11106 39.84235,-86.11039 39.84307,-86.10953 39.84487,-86.10738 39.84663,-86.10527 39.84747,-86.10427 39.84793,-86.10369</SHP>
<SHP FC="3">39.84793,-86.10369 39.84886,-86.10255 39.84949,-86.10172 39.85041,-86.10046 39.85088,-86.09985 39.85137,-86.09926 39.85169,-86.09888 39.85203,-86.09854 39.85237,-86.09821 39.85272,-86.09789 39.85307,-86.09758 39.85343,-86.09729 39.8542,-86.09673 39.85502,-86.09616</SHP>
<SHP FC="3">39.85502,-86.09616 39.85534,-86.09595 39.85631,-86.09528 39.85691,-86.09487 39.85751,-86.09443</SHP>
<SHP FC="3">39.85751,-86.09443 39.85808,-86.09399 39.85836,-86.09379</SHP>
<CF CN="0.97" FF="47.85" JF="1.39455" SP="39.84" SU="39.84" TY="TR"/>
</FI>
<!-- ... -->
</FIS>
</RW>
</RWS>
</TRAFFICML_REALTIME>
This is useful, since it tells me the exact road shape and its corresponding traffic data.
This is not the case when the Flow Item is broken up into multiple segments. Here is a sample JSON that I'm working with:
...
{
"FIS":[
{
"FI":[
{
...
"SHP":[
{
"value":[
"51.24274,7.13212 51.24311,7.13263 51.2432,7.13277 "
],
"FC":3
},
{
"value":[
"51.2432,7.13277 51.24345,7.13314 51.24363,7.13346 51.24382,7.13381 51.24398,7.13408 51.24408,7.13423 51.24418,7.13436 "
],
"FC":3
},
...
]
"CF":[
{
"SSS":{
"SS":[
{
"LE":1.07,
"SP":50.0,
"SU":52.63,
"FF":49.18,
"JF":0.0
},
{
"LE":0.37,
"SP":25.67,
"SU":25.67,
"FF":26.74,
"JF":0.37504
},
...
As you can see, the CF segments are decoupled from the shape of the road, unlike the previous XML example.
Is there any way to interpret this data that couples traffic congestion with the shape of the road?
Each traffic flow model consists of a location data of road segment represented in different location references (TMC, SHP)
and a currentFlow (CF) field describing the current traffic conditions.
If there are different traffic conditions within same road segment, then sub segments (SS) are included to provide more granular traffic conditions while CF having aggregated information.
Data model for traffic flow does not provide location data for each subsegment, however it can be derived using length information available on subsegment SS. Example: Traverse to shape points until it matches subsegment length (preferred using percentile length as length may vary due to different map version or length calculated from shape points does not accurately match with map)then continuing it until last SSS
I have the following POLYGON (in the image you can see the area it covers)
POLYGON((-74.05100448502202 4.7239278424321,-74.05092938316898 4.7241416902206,-74.04830618275201 4.7237460717602,-74.04643668306903 4.7234306460692,-74.04635688735101 4.7234105978214,-74.04636526925401 4.7233310730989,-74.046191260944 4.72327293317,-74.04579027069599 4.7232007594583,-74.04141290558402 4.7214258184083,-74.03746201170497 4.7197791822891,-74.03565688503801 4.7189879401666,-74.033484295736 4.7180897723398,-74.03098447693401 4.7170526009038,-74.028731840457 4.7161167561787,-74.02852820211899 4.7150714370973,-74.026398371001 4.6877232674918,-74.02558060109601 4.6874859863574,-74.02454587610401 4.686797564651,-74.024665108676 4.6863189291555,-74.025470986757 4.6857975214267,-74.02585246812498 4.6846813784365,-74.02580479605103 4.6834369175226,-74.01962984798399 4.684922743491,-74.028472839649 4.6765444849623,-74.032273278366 4.6775012677607,-74.03825980124901 4.6799297676049,-74.048215993474 4.6850422042295,-74.05718496514402 4.6867981911917,-74.05100448502202 4.7239278424321))
When I execute MBRIntersect, MBRContains and Within functions they return that the green marker is inside of the polygon, but it is not (as you can see in the image). I'm executing the next sentence to get that:
SET #g1 = ST_GeomFromText('POLYGON((-74.05100448502202 4.7239278424321,-74.05092938316898 4.7241416902206,-74.04830618275201 4.7237460717602,-74.04643668306903 4.7234306460692,-74.04635688735101 4.7234105978214,-74.04636526925401 4.7233310730989,-74.046191260944 4.72327293317,-74.04579027069599 4.7232007594583,-74.04141290558402 4.7214258184083,-74.03746201170497 4.7197791822891,-74.03565688503801 4.7189879401666,-74.033484295736 4.7180897723398,-74.03098447693401 4.7170526009038,-74.028731840457 4.7161167561787,-74.02852820211899 4.7150714370973,-74.026398371001 4.6877232674918,-74.02558060109601 4.6874859863574,-74.02454587610401 4.686797564651,-74.024665108676 4.6863189291555,-74.025470986757 4.6857975214267,-74.02585246812498 4.6846813784365,-74.02580479605103 4.6834369175226,-74.01962984798399 4.684922743491,-74.028472839649 4.6765444849623,-74.032273278366 4.6775012677607,-74.03825980124901 4.6799297676049,-74.048215993474 4.6850422042295,-74.05718496514402 4.6867981911917,-74.05100448502202 4.7239278424321))', 4326);
SELECT MBRContains(#g1, ST_PointFromText('POINT(-74.051585 4.680108)', 4326)) g1,
st_distance(ST_PointFromText('POINT(-74.051585 4.680108)', 4326), #g1) distance
and I'm getting
g1 distance
1 | 0.005489581062607619
But I was expecting
g1 distance
0 | 0.005489581062607619
I have try the following cases:
Save geometry assigning 4326 SRID.
Using other functions, getting same response.
I'm Using 5.7.14 MySQL version
What am I doing wrong?
I worked around this issue just validating that there's no distance. But, why am I getting this result from that functions?
I don't have a MySQL to play with right now. So i first try to duplicate your query in a SQL Server Spatial.
DECLARE #g1 geometry
DECLARE #h1 geometry
SET #g1= geometry::STGeomFromText('POLYGON((-74.05100448502202 4.7239278424321,-74.05092938316898 4.7241416902206,-74.04830618275201 4.7237460717602,-74.04643668306903 4.7234306460692,-74.04635688735101 4.7234105978214,-74.04636526925401 4.7233310730989,-74.046191260944 4.72327293317,-74.04579027069599 4.7232007594583,-74.04141290558402 4.7214258184083,-74.03746201170497 4.7197791822891,-74.03565688503801 4.7189879401666,-74.033484295736 4.7180897723398,-74.03098447693401 4.7170526009038,-74.028731840457 4.7161167561787,-74.02852820211899 4.7150714370973,-74.026398371001 4.6877232674918,-74.02558060109601 4.6874859863574,-74.02454587610401 4.686797564651,-74.024665108676 4.6863189291555,-74.025470986757 4.6857975214267,-74.02585246812498 4.6846813784365,-74.02580479605103 4.6834369175226,-74.01962984798399 4.684922743491,-74.028472839649 4.6765444849623,-74.032273278366 4.6775012677607,-74.03825980124901 4.6799297676049,-74.048215993474 4.6850422042295,-74.05718496514402 4.6867981911917,-74.05100448502202 4.7239278424321))', 4326);
SET #h1 = geometry::STGeomFromText('POINT(-74.051585 4.680108)', 4326)
SELECT #g1.STContains(#h1) contain, #g1.STDistance(#h1) distance
And the result is what you may expect:
contain distance
0 | 0.005489581062607675
Here is the reason behind this:
I am using STContains not MBRContains based on your description of what you are looking for. MBRContains function first create a Minimal Bounding Rectangle over your polygon, and use that new polygon feature do the contain judegement. In your example, the point does fall into the MBR of your polygon so thats why your MySQL result is not what you expect. And STContains is the right function you are looking for.
Official reference: Mysql spatial Link
I am trying to overlay a satellite image (a 6471x7669 jpg file) over Google Map using OL3. The image file's meta-data and projection info is provided as:
Driver: JP2ECW/ERDAS JPEG2000 (SDK 3.x)
Files: /mnt/NAIP/TN/2012/34084/m_3408403_ne_16_1_20120527_20120911.jp2
Size is 6471, 7669
Coordinate System is:
PROJCS["NAD83 / UTM zone 16N",
GEOGCS["NAD83",
DATUM["North_American_Datum_1983",
SPHEROID["GRS 1980",6378137,298.2572221010002,
AUTHORITY["EPSG","7019"]],
AUTHORITY["EPSG","6269"]],
PRIMEM["Greenwich",0],
UNIT["degree",0.0174532925199433],
AUTHORITY["EPSG","4269"]],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",0],
PARAMETER["central_meridian",-87],
PARAMETER["scale_factor",0.9996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
UNIT["metre",1,
AUTHORITY["EPSG","9001"]],
AUTHORITY["EPSG","26916"]]
Origin = (710739.000000000000000,3875921.000000000000000)
Pixel Size = (1.000000000000000,-1.000000000000000)
Metadata:
COLORSPACE=MULTIBAND
COMPRESSION_RATE_TARGET=9
VERSION=1
Corner Coordinates:
Upper Left ( 710739.000, 3875921.000) ( 84d41'26.44"W, 35d 0'14.31"N)
Lower Left ( 710739.000, 3868252.000) ( 84d41'33.42"W, 34d56' 5.56"N)
Upper Right ( 717210.000, 3875921.000) ( 84d37'11.35"W, 35d 0' 9.39"N)
Lower Right ( 717210.000, 3868252.000) ( 84d37'18.55"W, 34d56' 0.64"N)
Center ( 713974.500, 3872086.500) ( 84d39'22.44"W, 34d58' 7.49"N)
Band 1 Block=256x256 Type=Byte, ColorInterp=Undefined
Description = Band #1
Overviews: 3235x3834, 1617x1917, 808x958, 404x479, 202x239
Band 2 Block=256x256 Type=Byte, ColorInterp=Undefined
Description = Band #2
Overviews: 3235x3834, 1617x1917, 808x958, 404x479, 202x239
Band 3 Block=256x256 Type=Byte, ColorInterp=Undefined
Description = Band #3
Overviews: 3235x3834, 1617x1917, 808x958, 404x479, 202x239
Band 4 Block=256x256 Type=Byte, ColorInterp=Undefined
Description = Band #4
Overviews: 3235x3834, 1617x1917, 808x958, 404x479, 202x239
The problem I'm having is to interpret the data and figure out what projection to use (I'm not a geographer). I have already tested both EPSG:900913 and EPSG:3857 to transform to EPSG:4326, but it doesn't seem to work:
var lonlat = ol.proj.transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326');
The provided data mentions EPSG:7019, EPSG:6269, EPSG:4269, EPSG:9001, and EPSG:26916, none of which seem to have Proj4js definitions. The provided corner & center lat/lons coordinates are pretty accurate.
My questions are: is there an existing proj4.defs for this? If not, how can I create one? Any help on this is greatly appreciated.
UPDATE
Expanding on this question further: Initially we center the static image over Google Map just fine.
But not sure what transformation to use as the layers are moved together. In a nutshell what should be the transformation <transform> in this code?
view.on('change:center', function() {
var center = ol.proj.transform(view.getCenter(), <transform>, 'EPSG:4326');
gmap.setCenter(new google.maps.LatLng(center[1], center[0]))
});
You source image is in NAD83 UTM 16N or EPSG:26916 see http://spatialreference.org/ref/epsg/nad83-utm-zone-16n/
UTM is a Transverse Mercator projection with vertical 6 degree strips of the world projected onto a cylinder with its axis through the poles. Google maps uses a spherical Mercator (horizontal cylindrical) projection - EPSG:3857. The properties of these two are quite different - you will not be able to accurately overlay your 26916 image on a 3857 map without reprojecting it.
Have you looked at this http://openlayers.org/en/latest/examples/reprojection-image.html ?
Alternatively, you could use a GIS program of some sort to re-project your image to 3857 for easier composition with a 3857 map - say something like GlobalMapper.
I have the following MySQL query below. I'm trying to pull out the four sets of coordinates, then plot them on my custom Google v3 API page. (I also need it to "connect" the dots with blue lines as well)
Here is what the original "printable_text" column data looks like:
Grids : T04SR08W09NW
BestFit: 38.204326/-89.995942 38.204330/-89.993452
: 38.203490/-89.993451 38.203486/-89.995941
PreMark: NO Directional Boring: NO Depth>7Ft: NO
Here is my current MySQL query:
SELECT ticket
, SUBSTR(printable_text
, LOCATE('BestFit: ',printable_text)+9
, LOCATE('PreMark:', printable_text) - LOCATE('BestFit: '
, printable_text) - 9) AS coord
, REPLACE((SUBSTR(printable_text
, LOCATE('BestFit: ',printable_text)+9
, LOCATE('PreMark:', printable_text) - LOCATE('BestFit: '
, printable_text) - 9)),'/',',') AS coord
FROM tickets
WHERE ticket = 'A3041073'
Here is what I have extracted so far:
38.204326/-89.995942 38.204330/-89.993452 : 38.203490/-89.993451 38.203486/-89.995941
38.204326,-89.995942 38.204330,-89.993452 : 38.203490,-89.993451 38.203486,-89.995941
I'm guessing I need to get rid of the "/", "spaces", "colons", and feed the four coordinates to my Google API for plotting and connecting..?