def test_get_bounds(self): """context.CartoContext._get_bounds""" from cartoframes.layer import QueryLayer cc = cartoframes.CartoContext(base_url=self.baseurl, api_key=self.apikey) vals1 = {'minx': 0, 'maxx': 1, 'miny': 0, 'maxy': 2} vals2 = {'minx': 0, 'maxx': 1.5, 'miny': -0.5, 'maxy': 1.5} ans = {'west': 0, 'east': 1.5, 'south': -0.5, 'north': 2} # (MINX, MINY), (MINX, MAXY), (MAXX, MAXY), (MAXX, MINY), (MINX, MINY) # https://postgis.net/docs/ST_Envelope.html query = ''' WITH cte AS ( SELECT 'SRID=4326;POLYGON(({minx} {miny}, {minx} {maxy}, {maxx} {maxy}, {maxx} {miny}, {minx} {miny}))'::geometry AS the_geom ) SELECT 1 AS cartodb_id, the_geom, ST_Transform(the_geom, 3857) AS the_geom_webmercator FROM cte ''' layers = [ QueryLayer(query.format(**vals1)), QueryLayer(query.format(**vals2)) ] extent_ans = cc._get_bounds(layers) self.assertDictEqual(extent_ans, ans)
def test_cartocontext_map_geom_type(self): """context.CartoContext.map basemap geometry type defaults""" from cartoframes import Layer, QueryLayer cc = cartoframes.CartoContext(base_url=self.baseurl, api_key=self.apikey) # baseid1 = dark, labels1 = labels on top in named map name labels_polygon = cc.map(layers=Layer(self.test_read_table)) self.assertRegexpMatches(labels_polygon.__html__(), '.*baseid2_labels1.*', msg='labels should be on top since only a ' 'polygon layer is present') # baseid2 = voyager, labels0 = labels on bottom labels_point = cc.map(layers=Layer(self.test_point_table)) self.assertRegexpMatches(labels_point.__html__(), '.*baseid2_labels0.*', msg='labels should be on bottom because a ' 'point layer is present') labels_multi = cc.map( layers=[Layer(self.test_point_table), Layer(self.test_read_table)]) self.assertRegexpMatches(labels_multi.__html__(), '.*baseid2_labels0.*', msg='labels should be on bottom because a ' 'point layer is present') # create a layer with points and polys, but with more polys # should default to poly layer (labels on top) multi_geom_layer = QueryLayer(''' (SELECT the_geom, the_geom_webmercator, row_number() OVER () AS cartodb_id FROM "{polys}" WHERE the_geom IS NOT null LIMIT 10) UNION ALL (SELECT the_geom, the_geom_webmercator, (row_number() OVER ()) + 10 AS cartodb_id FROM "{points}" WHERE the_geom IS NOT null LIMIT 5) '''.format(polys=self.test_read_table, points=self.test_point_table)) multi_geom = cc.map(layers=multi_geom_layer) self.assertRegexpMatches(multi_geom.__html__(), '.*baseid2_labels1.*', msg='layer has more polys than points, so it ' 'should default to polys labels (on top)')
def test_cartocontext_map(self): """context.CartoContext.map normal usage""" from cartoframes import Layer, QueryLayer, BaseMap try: import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt except ImportError: plt = None cc = cartoframes.CartoContext(base_url=self.baseurl, api_key=self.apikey) # test with no layers - should produce basemap if plt: basemap_only_static_mpl = cc.map(interactive=False) cartoframes.context.HAS_MATPLOTLIB = False basemap_only_static = cc.map(interactive=False) basemap_only_interactive = cc.map(interactive=True) # are of the correct type instances if plt: self.assertIsInstance(basemap_only_static_mpl, plt.Axes) self.assertIsInstance(basemap_only_static, IPython.core.display.Image) self.assertIsInstance(basemap_only_interactive, IPython.core.display.HTML) # have the HTML innards that are to be expected if sys.version[0] == 3: self.assertRegex(basemap_only_static.data, ('^<img src="https://.*api/v1/map/static/named/' 'cartoframes_ver.*" />$')) self.assertRegex(basemap_only_interactive.data, '^<iframe srcdoc="<!DOCTYPE html>.*') elif sys.version[0] == 2: self.assertRegexMatches( basemap_only_static.data, ('^<img src="https://.*api/v1/map/static/named/' 'cartoframes_ver.*" />$')) self.assertRegexMatches(basemap_only_interactive.data, '^<iframe srcdoc="<!DOCTYPE html>.*') # test with labels on front labels_front = cc.map(layers=BaseMap('light', labels='front')) self.assertIsInstance(labels_front, IPython.core.display.HTML) # test with one Layer one_layer = cc.map(layers=Layer('tweets_obama')) self.assertIsInstance(one_layer, IPython.core.display.HTML) # test with two Layers two_layers = cc.map( layers=[Layer('tweets_obama'), Layer(self.test_read_table)]) self.assertIsInstance(two_layers, IPython.core.display.HTML) # test with one Layer, one QueryLayer onelayer_onequery = cc.map(layers=[ QueryLayer(''' SELECT * FROM tweets_obama LIMIT 100'''), Layer(self.test_read_table) ]) self.assertIsInstance(onelayer_onequery, IPython.core.display.HTML) # test with BaseMap, Layer, QueryLayer cc.map(layers=[ BaseMap('light'), QueryLayer(''' SELECT * FROM tweets_obama LIMIT 100''', color='favoritescount'), Layer(self.test_read_table) ]) # Errors # too many layers with self.assertRaises(ValueError): layers = [Layer('tweets_obama')] * 9 cc.map(layers=layers) # zoom needs to be specified with lng/lat with self.assertRaises(ValueError): cc.map(lng=44.3386, lat=68.2733) # only one basemap layer can be added with self.assertRaises(ValueError): cc.map(layers=[BaseMap('dark'), BaseMap('light')]) # only one time layer can be added with self.assertRaises(ValueError): cc.map(layers=[ Layer(self.test_read_table, time='cartodb_id'), Layer(self.test_read_table, time='cartodb_id') ]) # no geometry with self.assertRaises(ValueError): cc.map(layers=QueryLayer(''' SELECT null::geometry as the_geom, null::geometry as the_geom_webmercator, row_number() OVER () as cartodb_id FROM generate_series(1, 10) as m(i) '''))