Exemple #1
0
 def setUp(self):
     # color schemes with all different names
     self.burg = styling.burg(bins=4)
     self.burgYl = styling.burgYl(bins=4)
     self.redOr = styling.redOr(bins=4)
     self.orYel = styling.orYel(bins=4)
     self.peach = styling.peach(bins=4)
     self.pinkYl = styling.pinkYl(bins=4)
     self.mint = styling.mint(bins=4)
     self.bluGrn = styling.bluGrn(bins=4)
     self.darkMint = styling.darkMint(bins=4)
     self.emrld = styling.emrld(bins=4)
     self.bluYl = styling.bluYl(bins=4)
     self.teal = styling.teal(bins=4)
     self.tealGrn = styling.tealGrn(bins=4)
     self.purp = styling.purp(bins=4)
     self.purpOr = styling.purpOr(bins=4)
     self.sunset = styling.sunset(bins=4)
     self.magenta = styling.magenta(bins=4)
     self.sunsetDark = styling.sunsetDark(bins=4)
     self.brwnYl = styling.brwnYl(bins=4)
     self.armyRose = styling.armyRose(bins=4)
     self.fall = styling.fall(bins=4)
     self.geyser = styling.geyser(bins=4)
     self.temps = styling.temps(bins=4)
     self.tealRose = styling.tealRose(bins=4)
     self.tropic = styling.tropic(bins=4)
     self.earth = styling.earth(bins=4)
     self.antique = styling.antique(bins=4)
     self.bold = styling.bold(bins=4)
     self.pastel = styling.pastel(bins=4)
     self.prism = styling.prism(bins=4)
     self.safe = styling.safe(bins=4)
     self.vivid = styling.vivid(bins=4)
Exemple #2
0
    def test_querylayer_time_numeric(self):
        """layer.QueryLayer time with quantitative classification"""
        querylayer = QueryLayer(self.query, time='timecol', color='colorcol')
        # category type
        querylayer.style_cols['colorcol'] = 'number'
        querylayer.style_cols['timecol'] = 'date'
        querylayer.geom_type = 'point'

        # normal behavior for point geometries
        querylayer._setup([BaseMap(), querylayer], 1)  # pylint: disable=protected-access
        self.assertDictEqual(querylayer.scheme, styling.mint(5))
        # expect category maps query
        self.assertRegexpMatches(querylayer.query.strip(),
                                 r'^SELECT \*, colorcol as value '
                                 r'.*_wrap$')
        # cartocss should have cdb math mode
        self.assertRegexpMatches(querylayer.cartocss, r'.*avg\(colorcol\).*')
Exemple #3
0
    def test_querylayer_colors(self):
        """layer.QueryLayer color options tests"""

        # no color options passed
        basic = QueryLayer(self.query)
        self.assertEqual(basic.color, None)

        # check valid dict color options
        dict_colors = [{'column': 'mandrill', 'scheme': styling.armyRose(7)},
                       {'column': 'mercxx', 'scheme': {'bin_method': 'equal',
                                                       'bins': 7,
                                                       'name': 'Temps'}},
                       {'column': 'elephant',
                        'scheme': styling.redOr(10, bin_method='jenks')}]
        dict_colors_ans = ['mandrill', 'mercxx', 'elephant']
        dict_colors_scheme = [{'name': 'ArmyRose', 'bins': 7, 'bin_method': 'quantiles'},
                              {'name': 'Temps', 'bins': 7, 'bin_method': 'equal'},
                              {'name': 'RedOr', 'bins': 10, 'bin_method': 'jenks'}]
        for idx, val in enumerate(dict_colors):
            qlayer = QueryLayer(self.query, color=val)
            self.assertEqual(qlayer.color, dict_colors_ans[idx])
            self.assertEqual(qlayer.scheme, dict_colors_scheme[idx])

        # check valid string color options
        str_colors = ['#FF0000', 'aliceblue', 'cookie_monster']
        str_colors_ans = ['#FF0000', 'aliceblue', 'cookie_monster']
        str_scheme_ans = [None, None, styling.mint(5)]

        for idx, color in enumerate(str_colors):
            qlayer = QueryLayer(self.query, color=color)
            print(qlayer.color)
            self.assertEqual(qlayer.color, str_colors_ans[idx])
            self.assertEqual(qlayer.scheme, str_scheme_ans[idx])

        # Exception testing
        # color column cannot be a geometry column
        with self.assertRaises(ValueError,
                               msg='color clumn cannot be a geometry column'):
            QueryLayer(self.query, color='the_geom')

        # color dict must have a 'column' key
        with self.assertRaises(ValueError,
                               msg='color dict must have a `column` key'):
            QueryLayer(self.query, color={'scheme': styling.vivid(10)})
Exemple #4
0
    def __init__(self,
                 query,
                 time=None,
                 color=None,
                 size=None,
                 tooltip=None,
                 legend=None):

        self.query = query
        self.style_cols = set()

        # color, scheme = self._get_colorscheme()
        # time = self._get_timescheme()
        # size = self._get_sizescheme()
        # If column was specified, force a scheme
        # It could be that there is a column named 'blue' for example
        if isinstance(color, dict):
            if 'column' not in color:
                raise ValueError("color must include a 'column' value")
            scheme = color.get('scheme', mint(5))
            color = color['column']
            self.style_cols.add(color)
        elif (color and color[0] != '#'
              and color not in webcolors.CSS3_NAMES_TO_HEX):
            # color specified that is not a web color or hex value so its
            #  assumed to be a column name
            color = color
            self.style_cols.add(color)
            scheme = mint(5)
        else:
            # assume it's a color
            color = color
            scheme = None

        if time:
            if isinstance(time, dict):
                if 'column' not in time:
                    raise ValueError("time must include a 'column' value")
                time_column = time['column']
                time_options = time
            elif isinstance(time, str):
                time_column = time
                time_options = {}
            else:
                raise ValueError('`time` should be a column name or '
                                 'dictionary of styling options.')

            self.style_cols.add(time_column)
            time = {
                'column': time_column,
                'method': 'count',
                'cumulative': False,
                'frames': 256,
                'duration': 30,
            }
            time.update(time_options)

        size = size or 10
        if isinstance(size, str):
            size = {'column': size}
        if isinstance(size, dict):
            if 'column' not in size:
                raise ValueError("Size must include a 'column' key/value")
            if time:
                raise ValueError("When time is specified, size can "
                                 "only be a fixed size")
            old_size = size
            size = {
                'range': [5, 25],
                'bins': 10,
                'bin_method': BinMethod.quantiles,
            }
            size.update(old_size)
            # Since we're accessing min/max, convert range into a list
            size['range'] = list(size['range'])
            self.style_cols.add(size['column'])

        self.color = color
        self.scheme = scheme
        self.size = size
        self.time = time
        self.tooltip = tooltip
        self.legend = legend
        self._validate_columns()
Exemple #5
0
    def test_querylayer_colors(self):
        """layer.QueryLayer color options tests"""

        # no color options passed
        basic = QueryLayer(self.query)
        self.assertEqual(basic.color, None)

        # check valid dict color options
        dict_colors = [{
            'column': 'mandrill',
            'scheme': styling.armyRose(7)
        }, {
            'column': 'mercxx',
            'scheme': {
                'bin_method': 'equal',
                'bins': 7,
                'name': 'Temps'
            }
        }, {
            'column': 'elephant',
            'scheme': styling.redOr(10, bin_method='jenks')
        }]
        dict_colors_ans = ['mandrill', 'mercxx', 'elephant']
        dict_colors_scheme = [{
            'name': 'ArmyRose',
            'bins': 7,
            'bin_method': 'quantiles'
        }, {
            'name': 'Temps',
            'bins': 7,
            'bin_method': 'equal'
        }, {
            'name': 'RedOr',
            'bins': 10,
            'bin_method': 'jenks'
        }]
        for idx, val in enumerate(dict_colors):
            qlayer = QueryLayer(self.query, color=val)
            self.assertEqual(qlayer.color, dict_colors_ans[idx])
            self.assertEqual(qlayer.scheme, dict_colors_scheme[idx])

        # check valid string color options
        str_colors = ('#FF0000', 'aliceblue', 'cookie_monster', 'big_bird')
        str_colors_ans = ('#FF0000', 'aliceblue', 'cookie_monster', 'big_bird')
        str_scheme_ans = (None, None, styling.mint(5), styling.antique(10))

        for idx, color in enumerate(str_colors):
            qlayer = QueryLayer(self.query, color=color)
            qlayer.geom_type = 'point'
            if color == 'cookie_monster':
                qlayer.style_cols[color] = 'number'
                qlayer._setup([BaseMap(), qlayer], 1)  # pylint: disable=protected-access
            elif color == 'big_bird':
                qlayer.style_cols[color] = 'string'
                qlayer._setup([BaseMap(), qlayer], 1)  # pylint: disable=protected-access
            self.assertEqual(qlayer.color, str_colors_ans[idx])
            self.assertEqual(qlayer.scheme, str_scheme_ans[idx])

        with self.assertRaises(ValueError,
                               msg='styling value cannot be a date'):
            qlayer = QueryLayer(self.query, color='datetime_column')
            qlayer.style_cols['datetime_column'] = 'date'
            qlayer._setup([BaseMap(), qlayer], 1)  # pylint: disable=protected-access

        # Exception testing
        # color column cannot be a geometry column
        with self.assertRaises(ValueError,
                               msg='color clumn cannot be a geometry column'):
            QueryLayer(self.query, color='the_geom')

        # color dict must have a 'column' key
        with self.assertRaises(ValueError,
                               msg='color dict must have a `column` key'):
            QueryLayer(self.query, color={'scheme': styling.vivid(10)})
Exemple #6
0
    def _setup(self, layers, layer_idx):
        basemap = layers[0]

        # if color not specified, choose a default
        # choose color time default
        if self.time:
            # default torque color
            self.color = self.color or '#2752ff'
        else:
            self.color = self.color or DEFAULT_COLORS[layer_idx]
        # choose appropriate scheme if not already specified
        if (not self.scheme) and (self.color in self.style_cols):
            if self.style_cols[self.color] in ('string', 'boolean', ):
                self.scheme = antique(10)
            elif self.style_cols[self.color] in ('number', ):
                self.scheme = mint(5)
            elif self.style_cols[self.color] in ('date', 'geometry', ):
                raise ValueError(
                    'Cannot style column `{col}` of type `{type}`. It must be '
                    'numeric, text, or boolean.'.format(
                        col=self.color, type=self.style_cols[self.color]))

        if self.time:
            # validate time column information
            if self.geom_type != 'point':
                raise ValueError('Cannot do time-based maps with data in '
                                 '`{query}` since this table does not contain '
                                 'point geometries'.format(
                                     query=self.orig_query))
            elif self.style_cols[self.time['column']] not in (
                    'number', 'date', ):
                raise ValueError('Cannot create an animated map from column '
                                 '`{col}` because it is of type {t1}. It must '
                                 'be of type number or date.'.format(
                                     col=self.time['column'],
                                     t1=self.style_cols[self.time['column']]))

            # don't use turbo-carto for animated maps
            column = self.time['column']
            frames = self.time['frames']
            method = self.time['method']
            duration = self.time['duration']
            if (self.color in self.style_cols and
                    self.style_cols[self.color] in ('string', 'boolean', )):
                self.query = minify_sql([
                    'SELECT',
                    '    orig.*, __wrap.cf_value_{col}',
                    'FROM ({query}) AS orig, (',
                    '    SELECT',
                    '      row_number() OVER (',
                    '        ORDER BY val_{col}_cnt DESC) AS cf_value_{col},',
                    '      {col}',
                    '    FROM (',
                    '        SELECT {col}, count({col}) AS val_{col}_cnt',
                    '        FROM ({query}) as orig',
                    '        GROUP BY {col}',
                    '        ORDER BY 2 DESC',
                    '    ) AS _wrap',
                    ') AS __wrap',
                    'WHERE __wrap.{col} = orig.{col}',
                ]).format(col=self.color, query=self.orig_query)
                agg_func = '\'CDB_Math_Mode(cf_value_{})\''.format(self.color)
                self.scheme = {
                    'bins': [str(i) for i in range(1, 11)],
                    'name': (self.scheme.get('name') if self.scheme
                             else 'Bold'),
                    'bin_method': '', }
            elif (self.color in self.style_cols and
                  self.style_cols[self.color] in ('number', )):
                self.query = ' '.join([
                    'SELECT *, {col} as value',
                    'FROM ({query}) as _wrap'
                ]).format(col=self.color, query=self.orig_query)
                agg_func = '\'avg({})\''.format(self.color)
            else:
                agg_func = "'{method}(cartodb_id)'".format(
                    method=method)
            self.torque_cartocss = cssify({
                'Map': {
                    '-torque-frame-count': frames,
                    '-torque-animation-duration': duration,
                    '-torque-time-attribute': "'{}'".format(column),
                    '-torque-aggregation-function': agg_func,
                    '-torque-resolution': 1,
                    '-torque-data-aggregation': ('cumulative'
                                                 if self.time['cumulative']
                                                 else 'linear'),
                },
            })
            self.cartocss = (self.torque_cartocss
                             + self._get_cartocss(basemap, has_time=True))
        else:
            # use turbo-carto for non-animated maps
            self.cartocss = self._get_cartocss(basemap)