Example #1
0
 def _get_newuser_bitmap(self, day=None, Type='dau'):
     """
     返回新用户当日登陆记录bitmap对象
     适配记录每日新用户id偏移量的数据存储方式
     """
     day = day or self.baseDay
     offsets = 0
     dauBitmap = Bitmap()
     if day:
         if Type == 'mau':
             day = datetime(day.year, day.month, 1)
         hKey = (self.config.dau_keys_conf['newuser'],
                 day.strftime(self.config.DATE_FORMAT))
         # dauBitmap = self._get_cache(hKey) or dauBitmap
         # cached = self._get_cache(hKey)
         # if cached is None or True:
         if True:
             offsets = self.REDIS.hget(*hKey)
             if not offsets:
                 return dauBitmap
             offsets = int(offsets)
             bmp = ((day == self.baseDay and Type == 'dau')
                    and Bitmap(self.baseBitmap)
                    or self._make_bitmap(day, Type))
             s = time.time()
             dauBitmap = Bitmap(bmp)  # 生成新的实例,避免被篡改
             dauBitmap[:offsets] = False
             # self._cache(hKey, dauBitmap)
         else:
             dauBitmap = cached
     logging.debug('get nu bitmap: %s Sec' % (time.time() - s))
     return dauBitmap
Example #2
0
 def _get_filter_bitmap(self, redis_cli, filtername, filterclass):
     """
     由数据源获取筛选条件 BitMap
     """
     logging.debug(self.redis_cli)
     redis_cli = redis_cli or self.redis_cli
     if not isinstance(redis_cli, redis.client.Redis):
         raise TypeError, "Need redis connection but not found"
     fKey_format = self.config.filter_keys_conf.get(filtername)
     if not fKey_format:
         raise ValueError, "Can not find the key \'%s\' in self.config.filter_keys_conf" % k
     logging.debug('%s, %s, %s',fKey_format,filtername,filterclass) 
     fKey  = fKey_format.format(**{filtername:filterclass})
     cached =  self._cache.get_cache(fKey)
     if cached is None:
         fBits = redis_cli.get(fKey)
         fBm   = Bitmap()
         if fBits:
             fBm.frombytes(fBits)
         else:
             fBm   = Bitmap('0')
         self._cache.set(fKey, fBm)
     else:
         fBm = cached
     return fBm
Example #3
0
 def _make_bitmap(self, day=None, Type='dau'):
     """
     initial and return dwarf.Bitmap object
     """
     # logging.info('make_bitmap:%s %s', day, Type)
     s = time.time()
     dauBitmap = Bitmap()
     if day:
         DAU_KEY = self.config.dau_keys_conf[Type]
         if Type in ('mau', 'mnu', 'mru'):
             dauKey = DAU_KEY.format(
                 month=day.strftime(self.config.MONTH_FORMAT))
         else:
             dauKey = DAU_KEY.format(
                 date=day.strftime(self.config.DATE_FORMAT))
         dauBitmap = Bitmap()
         cached = self._get_cache(dauKey)
         if cached:
             bitsDau = cached
             if cached is 'None':
                 bitsDau = None
         else:
             logging.debug('no cache:%s', dauKey)
             bitsDau = self.REDIS.get(dauKey)
             self._cache(dauKey, bitsDau or 'None')
         if bitsDau:
             dauBitmap.frombytes(bitsDau)
             # logging.debug('Init bitmap:Count: %s' % (dauBitmap.count()))
             if self.filters:
                 dauBitmap.filter(self.filters)
                 # logging.info('Filter bitmap: f-%s b-%s' % (self.filters.count(), dauBitmap.count()))
         # self._cache(dauKey, dauBitmap)
     logging.debug('_make_bitmap Handler:%s %s - %s Sec' %
                   (day, Type, time.time() - s))
     return dauBitmap
Example #4
0
 def _make_bitmap(self, day=None, Type='dau'):
     """
     initial and return dwarf.Bitmap object
     """
     # logging.info('make_bitmap:%s %s', day, Type)
     s = time.time()
     dauBitmap  = Bitmap()
     if day:
         DAU_KEY  = self.config.dau_keys_conf[Type]
         if Type in ('mau','mnu','mru'):
             dauKey   = DAU_KEY.format(month=day.strftime(self.config.MONTH_FORMAT))
         else:
             dauKey   = DAU_KEY.format(date=day.strftime(self.config.DATE_FORMAT))
         dauBitmap = Bitmap()
         cached = self._get_cache(dauKey)
         if cached:
             bitsDau = cached
             if cached is 'None':
                 bitsDau = None
         else:
             logging.debug('no cache:%s',dauKey)
             bitsDau  = self.REDIS.get(dauKey)
             self._cache(dauKey, bitsDau or 'None')
         if bitsDau:
             dauBitmap.frombytes(bitsDau)
             # logging.debug('Init bitmap:Count: %s' % (dauBitmap.count()))
             if self.filters:
                 dauBitmap.filter(self.filters)
                 # logging.info('Filter bitmap: f-%s b-%s' % (self.filters.count(), dauBitmap.count()))
         # self._cache(dauKey, dauBitmap)
     logging.debug('_make_bitmap Handler:%s %s - %s Sec' % (day,Type,time.time()-s))
     return dauBitmap
Example #5
0
 def _get_filter_bitmap(self, redis_cli, filtername, filterclass):
     """
     由数据源获取筛选条件 BitMap
     """
     logging.debug(self.redis_cli)
     redis_cli = redis_cli or self.redis_cli
     if not isinstance(redis_cli, redis.client.Redis):
         raise TypeError, "Need redis connection but not found"
     fKey_format = self.config.filter_keys_conf.get(filtername)
     if not fKey_format:
         raise ValueError, "Can not find the key \'%s\' in self.config.filter_keys_conf" % k
     logging.debug('%s, %s, %s', fKey_format, filtername, filterclass)
     fKey = fKey_format.format(**{filtername: filterclass})
     cached = self._cache.get_cache(fKey)
     if cached is None:
         fBits = redis_cli.get(fKey)
         fBm = Bitmap()
         if fBits:
             fBm.frombytes(fBits)
         else:
             fBm = Bitmap('0')
         self._cache.set(fKey, fBm)
     else:
         fBm = cached
     return fBm
Example #6
0
    def __init__(self,
                 baseday=None,
                 redis_cli=None,
                 filters=None,
                 cache=True,
                 config=None):
        s = time.time()
        # logging.info('init austat: baseday %s, config: %s', baseday, config and config.dau_keys_conf or '')
        if not redis_cli:
            raise KeyError, 'Redis connection not found'
        if not config:
            self.config = dauconfig
        else:
            self.config = config

        self.cache = _Cache()
        # self._cache_dict          = {}
        # self._max_cache_lens = 1024
        self.REDIS = redis_cli
        self.baseDay = baseday
        self.filters = filters
        self._is_cache = cache
        self.baseBitmap = self._make_bitmap(baseday)
        self.newUserBitmap = Bitmap()
Example #7
0
    def __init__(self, baseday=None, redis_cli=None,
     filters=None, cache=True, config=None):
        s = time.time()
        # logging.info('init austat: baseday %s, config: %s', baseday, config and config.dau_keys_conf or '')
        if not redis_cli:
            raise KeyError,'Redis connection not found'
        if not config:
            self.config = dauconfig
        else:
            self.config = config

        self.cache = _Cache()
        # self._cache_dict          = {}
        # self._max_cache_lens = 1024
        self.REDIS          = redis_cli
        self.baseDay        = baseday
        self.filters        = filters
        self._is_cache      = cache
        self.baseBitmap     = self._make_bitmap(baseday) 
        self.newUserBitmap  = Bitmap()
Example #8
0
class AUstat():


    def __init__(self, baseday=None, redis_cli=None,
     filters=None, cache=True, config=None):
        s = time.time()
        # logging.info('init austat: baseday %s, config: %s', baseday, config and config.dau_keys_conf or '')
        if not redis_cli:
            raise KeyError,'Redis connection not found'
        if not config:
            self.config = dauconfig
        else:
            self.config = config

        self.cache = _Cache()
        # self._cache_dict          = {}
        # self._max_cache_lens = 1024
        self.REDIS          = redis_cli
        self.baseDay        = baseday
        self.filters        = filters
        self._is_cache      = cache
        self.baseBitmap     = self._make_bitmap(baseday) 
        self.newUserBitmap  = Bitmap()


    def _get_cache(self, key):
        logging.debug('get from cache: %s', key)
        return self.cache.get_cache(key)

    def _cache(self, key, value):
        if self._is_cache:
            return self.cache._set_cache(key, value)
    


    def _list_day(self, fday=None, tday=None):
        """
        return the date string list from fday to tday
        """
        date_fday   = fday or date.today()
        date_tday   = tday or date.today()
        days        = (date_tday - date_fday).days+1
        dayList     = [date_fday+timedelta(v) for v in range(days)] 
        return dayList        

    def _make_bitmap(self, day=None, Type='dau'):
        """
        initial and return dwarf.Bitmap object
        """
        # logging.info('make_bitmap:%s %s', day, Type)
        s = time.time()
        dauBitmap  = Bitmap()
        if day:
            DAU_KEY  = self.config.dau_keys_conf[Type]
            if Type in ('mau','mnu','mru'):
                dauKey   = DAU_KEY.format(month=day.strftime(self.config.MONTH_FORMAT))
            else:
                dauKey   = DAU_KEY.format(date=day.strftime(self.config.DATE_FORMAT))
            dauBitmap = Bitmap()
            cached = self._get_cache(dauKey)
            if cached:
                bitsDau = cached
                if cached is 'None':
                    bitsDau = None
            else:
                logging.debug('no cache:%s',dauKey)
                bitsDau  = self.REDIS.get(dauKey)
                self._cache(dauKey, bitsDau or 'None')
            if bitsDau:
                dauBitmap.frombytes(bitsDau)
                # logging.debug('Init bitmap:Count: %s' % (dauBitmap.count()))
                if self.filters:
                    dauBitmap.filter(self.filters)
                    # logging.info('Filter bitmap: f-%s b-%s' % (self.filters.count(), dauBitmap.count()))
            # self._cache(dauKey, dauBitmap)
        logging.debug('_make_bitmap Handler:%s %s - %s Sec' % (day,Type,time.time()-s))
        return dauBitmap

    def make_bitmap(self, day=None, Type='dau'):
        return self._make_bitmap(day, Type)


    def get_newuser_bitmap(self, day=None, Type='dnu'):
        """
        返回 day 或 day 所在月份的新用户bitmap对象
        """
        bmap = self._make_bitmap(day, Type)
        # logging.info('nbm: %s , %s', day, bmap.count())
        if bmap:
            # logging.info('nbm: %s , %s', day, bmap.length())
            return bmap
        '''
        如果没有新用户的分区间映射数据,则按照偏移量获取新用户映射数据
        '''
        Type = Type=='dnu' and 'dau' or 'mau' 
        bmap = self._get_newuser_bitmap(day, Type)
        return bmap

    def _get_newuser_bitmap(self, day=None, Type='dau'):
        """
        返回新用户当日登陆记录bitmap对象
        适配记录每日新用户id偏移量的数据存储方式
        """
        day = day or self.baseDay
        offsets = 0
        dauBitmap = Bitmap() 
        if day:
            if Type=='mau':
                day = datetime(day.year, day.month, 1)
            hKey = (self.config.dau_keys_conf['newuser'], 
                    day.strftime(self.config.DATE_FORMAT))
            # dauBitmap = self._get_cache(hKey) or dauBitmap
            # cached = self._get_cache(hKey)
            # if cached is None or True:
            if True:
                offsets = self.REDIS.hget(*hKey)
                if not offsets:
                    return dauBitmap
                offsets = int(offsets)
                bmp = ((day==self.baseDay and Type=='dau')
                 and Bitmap(self.baseBitmap) or self._make_bitmap(day, Type))
                s = time.time()
                dauBitmap = Bitmap(bmp) # 生成新的实例,避免被篡改
                dauBitmap[:offsets] = False
                # self._cache(hKey, dauBitmap)
            else:
                dauBitmap = cached
        logging.debug('get nu bitmap: %s Sec' % (time.time()-s))
        return dauBitmap

    def get_dau(self, day=None):
        """
        return the dau number
        if day is provided then return the dau of the day
        """
        if not day:
            return self.baseBitmap.count()
        return self._make_bitmap(day).count()

    def get_dnu(self, day=None):
        """
        return the daily count of new user number
        """
        if not day:
            return self.newUserBitmap.count()
        return self.get_newuser_bitmap(day).count()

    def get_dru(self, day=None):
        """
        return the daily count of new user number
        """
        if not day:
            return 0
        return self._make_bitmap(day, 'dru').count()

    def get_mau(self, date=None):
        if not date:
            date = self.baseDay
        return self._make_bitmap(date, 'mau').count()

    def get_mnu(self, date=None):
        if not date:
            date = self.baseDay
        return self.get_newuser_bitmap(date, 'mnu').count()

    def get_mru(self, date=None):
        if not date:
            date = self.baseDay
        return self._make_bitmap(date, 'mru').count()

    def list_dau(self, fday=None, tday=None):
        """
        return a list of daily active user's number from fday to tday
        list_dau(string, string) -> [(date1, number),(date2, number)....]
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, map(self.get_dau,dayList))

    def list_dnu(self, fday=None, tday=None):
        """
        return a list of daily new user count from fday to tday
        list_dnu(string, string) -> [(date1, number),(date2, number)....]
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, map(self.get_dnu,dayList))

    def list_dru(self, fday=None, tday=None):
        """
        return a list of daily recharge user from fday to tday
        list_dru(string, string) -> [(date1, number),(date2, number)....]
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, map(self.get_dru, dayList))

    def list_mau(self, fday, tday):
        """
        month active user count
        list_mau(string, string) -> [(datetime1, int),(datetime2,int),....]
        """
        lMonth = util.month1stdate(fday, tday)
        return zip(lMonth, map(self.get_mau, lMonth))

    def list_mnu(self, fday, tday):
        """
        monthly new user count
        list_mnu(string, string) -> [(datetime1, int),(datetime2,int),....]
        """
        lMonth = util.month1stdate(fday, tday)
        return zip(lMonth, map(self.get_mnu, lMonth))

    def list_mru(self, fday, tday):
        """
        monthly rechange user count
        list_mnu(string, string) -> [(datetime1, int),(datetime2,int),....]
        """
        lMonth = util.month1stdate(fday, tday)
        return zip(lMonth, map(self.get_mru, lMonth))

    def mau(self, fday=None, tday=None):
        """
        return the Merged Active Users count from fday to tday
        """
        dayList = self._list_day(fday, tday)
        BaseBM  = self._make_bitmap()
        for day in dayList:
            BaseBM.merge(self._make_bitmap(day))
        return BaseBM.count()

    def get_30days_mau(self):
        """
        return the merged active user number in the last 30 days before
        self.baseDay
        """
        fday = self.baseDay-timedelta(days=30)
        return self.mau(fday=fday, tday=self.baseDay)

    def get_7days_mau(self):
        """
        return the last 7 days' active user number before baseDay
        """
        fday = self.baseDay-timedelta(days=7)
        return self.mau(fday=fday, tday=self.baseDay)

    def list_1day_renu(self,fday,tday):
        """
        return the next day's new user retained
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList,[self._get_ndays_renu(d,1) for d in dayList])

    def list_7day_renu(self,fday,tday):
        """
        return the seventh day's new user retained
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList,[self._get_ndays_renu(d,7) for d in dayList])

    def list_30day_renu(self,fday,tday):
        """
        return the thirtieth day's new user retained
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList,[self._get_ndays_renu(d,30) for d in dayList])

    def _get_ndays_renu(self,day,num):
        return self.get_newuser_bitmap(day)._and_count(
            self.make_bitmap(day+timedelta(days=num)))

    def retained(self, day):
        """
        return the retained user number of baseDay in the givend day
        """
        bm  = self._make_bitmap(day)
        return self.baseBitmap.retained(bm)

    def get_retained(self, fday, tday):
        """
        the self.baseday's daily retained number from fday to tday
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, 
            self.baseBitmap.retained_count(
                 (self._make_bitmap(day) for day in dayList)
                )
            )

    def daily_retained_list(self, fday, tday):
        """
        the fday's retained number from fday to today
        """
        dayList = self._list_day(fday,tday)
        return zip(dayList, 
            self.make_bitmap(dayList[0],'dau').retained_count(
                 (self.make_bitmap(day, 'dau') for day in dayList)
                )
            )

    def customized_retained_list(self, base_day, day_list=[]):
        """
        the  day_list's retained number from fday to today
        :param base_day: the base day
        :param day_list: eg :[datetime,datetime], should not contain base_day
        :return:
        """
        auBitmap = self.make_bitmap(base_day, 'dau')
        return [(base_day, auBitmap.count())] + \
               zip(day_list, self._retained_value(base_day, day_list, 'dau'))

    def get_month_retained(self, fday, tday):
        """
        monthly retained au count from fday's month to tday's month
        """
        lMdates1 = util.month1stdate(fday, tday)
        return zip(lMdates1,
            self.make_bitmap(lMdates1[0],'mau').retained_count(
                    (self._make_bitmap(date, 'mau') for date in lMdates1)
                )
            )

    def get_retained_nu(self, fday, tday):
        """
        return the list of newuser retained number and the date string
        """
        dayList = self._list_day(fday, tday)
        if not self.newUserBitmap:
            self.newUserBitmap = self.get_newuser_bitmap(self.baseDay)
        # logging.info('self.nUB: %s', self.newUserBitmap.count())
        return zip(dayList, 
            self.newUserBitmap.retained_count(
                 (self.make_bitmap(day) for day in dayList)
                )
            )

    def daily_nu_retained_list(self, fday, tday):
        """
        fday's newuser retained number from fday to tday
        """
        dayList = self._list_day(fday, tday)
        nuBitmap = self.get_newuser_bitmap(dayList[0])
        return [[dayList.pop(0),nuBitmap.count()]]+zip(dayList, 
            nuBitmap.retained_count(
                 (self.make_bitmap(day, 'dau') for day in dayList)
                )
            )

    def customized_nu_retained_list(self, base_day, day_list=[]):
        """
        the day_list's retained number
        :param base_day: the base day
        :param day_list: eg :[datetime, datetime], should not contain base_day
        :return:
        """
        nuBitmap = self.get_newuser_bitmap(base_day)
        return [(base_day, nuBitmap.count())] + zip(day_list,
                  self._retained_value(base_day, day_list, 'dnu'))


    def get_month_retained_nu(self, fday, tday):
        """
        Monthly newuser retained count from fday's month to tday's month
        """
        lMdates1    = util.month1stdate(fday, tday)
        MnuBitmap   = self.get_newuser_bitmap(lMdates1[0], 'mnu')
        # logging.info('Newusers count: %s', MnuBitmap.count())
        return [[lMdates1.pop(0), MnuBitmap.count()]]+zip(lMdates1,
            MnuBitmap.retained_count(
                 (self._make_bitmap(date, 'mau') for date in lMdates1)
                )
            )


    def retained_by_daylist(self, dayList):
        return zip(dayList, self.baseBitmap.retained_count(
                (self._make_bitmap(day) for day in dayList)
            ))

    def retained_nu_by_daylist(self,dayList):
        return zip(dayList, 
            self.newUserBitmap.retained_count(
                 (self._make_bitmap(day) for day in dayList)
                )
            )

    def _retained_value(self, day, day_list, Type='dau'):
        retained_list = []
        if Type == 'dau':
            day_bitmap = self.make_bitmap(day, Type)
        elif Type == 'dnu':
            day_bitmap = self.get_newuser_bitmap(day)

        for t_day in day_list:
            retained_list.append(day_bitmap._and_count(
                self.make_bitmap(t_day, 'dau')
            ))
        return retained_list
Example #9
0
class AUstat():
    def __init__(self,
                 baseday=None,
                 redis_cli=None,
                 filters=None,
                 cache=True,
                 config=None):
        s = time.time()
        # logging.info('init austat: baseday %s, config: %s', baseday, config and config.dau_keys_conf or '')
        if not redis_cli:
            raise KeyError, 'Redis connection not found'
        if not config:
            self.config = dauconfig
        else:
            self.config = config

        self.cache = _Cache()
        # self._cache_dict          = {}
        # self._max_cache_lens = 1024
        self.REDIS = redis_cli
        self.baseDay = baseday
        self.filters = filters
        self._is_cache = cache
        self.baseBitmap = self._make_bitmap(baseday)
        self.newUserBitmap = Bitmap()

    def _get_cache(self, key):
        logging.debug('get from cache: %s', key)
        return self.cache.get_cache(key)

    def _cache(self, key, value):
        if self._is_cache:
            return self.cache._set_cache(key, value)

    def _list_day(self, fday=None, tday=None):
        """
        return the date string list from fday to tday
        """
        date_fday = fday or date.today()
        date_tday = tday or date.today()
        days = (date_tday - date_fday).days + 1
        dayList = [date_fday + timedelta(v) for v in range(days)]
        return dayList

    def _make_bitmap(self, day=None, Type='dau'):
        """
        initial and return dwarf.Bitmap object
        """
        # logging.info('make_bitmap:%s %s', day, Type)
        s = time.time()
        dauBitmap = Bitmap()
        if day:
            DAU_KEY = self.config.dau_keys_conf[Type]
            if Type in ('mau', 'mnu', 'mru'):
                dauKey = DAU_KEY.format(
                    month=day.strftime(self.config.MONTH_FORMAT))
            else:
                dauKey = DAU_KEY.format(
                    date=day.strftime(self.config.DATE_FORMAT))
            dauBitmap = Bitmap()
            cached = self._get_cache(dauKey)
            if cached:
                bitsDau = cached
                if cached is 'None':
                    bitsDau = None
            else:
                logging.debug('no cache:%s', dauKey)
                bitsDau = self.REDIS.get(dauKey)
                self._cache(dauKey, bitsDau or 'None')
            if bitsDau:
                dauBitmap.frombytes(bitsDau)
                # logging.debug('Init bitmap:Count: %s' % (dauBitmap.count()))
                if self.filters:
                    dauBitmap.filter(self.filters)
                    # logging.info('Filter bitmap: f-%s b-%s' % (self.filters.count(), dauBitmap.count()))
            # self._cache(dauKey, dauBitmap)
        logging.debug('_make_bitmap Handler:%s %s - %s Sec' %
                      (day, Type, time.time() - s))
        return dauBitmap

    def make_bitmap(self, day=None, Type='dau'):
        return self._make_bitmap(day, Type)

    def get_newuser_bitmap(self, day=None, Type='dnu'):
        """
        返回 day 或 day 所在月份的新用户bitmap对象
        """
        bmap = self._make_bitmap(day, Type)
        # logging.info('nbm: %s , %s', day, bmap.count())
        if bmap:
            # logging.info('nbm: %s , %s', day, bmap.length())
            return bmap
        '''
        如果没有新用户的分区间映射数据,则按照偏移量获取新用户映射数据
        '''
        Type = Type == 'dnu' and 'dau' or 'mau'
        bmap = self._get_newuser_bitmap(day, Type)
        return bmap

    def _get_newuser_bitmap(self, day=None, Type='dau'):
        """
        返回新用户当日登陆记录bitmap对象
        适配记录每日新用户id偏移量的数据存储方式
        """
        day = day or self.baseDay
        offsets = 0
        dauBitmap = Bitmap()
        if day:
            if Type == 'mau':
                day = datetime(day.year, day.month, 1)
            hKey = (self.config.dau_keys_conf['newuser'],
                    day.strftime(self.config.DATE_FORMAT))
            # dauBitmap = self._get_cache(hKey) or dauBitmap
            # cached = self._get_cache(hKey)
            # if cached is None or True:
            if True:
                offsets = self.REDIS.hget(*hKey)
                if not offsets:
                    return dauBitmap
                offsets = int(offsets)
                bmp = ((day == self.baseDay and Type == 'dau')
                       and Bitmap(self.baseBitmap)
                       or self._make_bitmap(day, Type))
                s = time.time()
                dauBitmap = Bitmap(bmp)  # 生成新的实例,避免被篡改
                dauBitmap[:offsets] = False
                # self._cache(hKey, dauBitmap)
            else:
                dauBitmap = cached
        logging.debug('get nu bitmap: %s Sec' % (time.time() - s))
        return dauBitmap

    def get_dau(self, day=None):
        """
        return the dau number
        if day is provided then return the dau of the day
        """
        if not day:
            return self.baseBitmap.count()
        return self._make_bitmap(day).count()

    def get_dnu(self, day=None):
        """
        return the daily count of new user number
        """
        if not day:
            return self.newUserBitmap.count()
        return self.get_newuser_bitmap(day).count()

    def get_dru(self, day=None):
        """
        return the daily count of new user number
        """
        if not day:
            return 0
        return self._make_bitmap(day, 'dru').count()

    def get_mau(self, date=None):
        if not date:
            date = self.baseDay
        return self._make_bitmap(date, 'mau').count()

    def get_mnu(self, date=None):
        if not date:
            date = self.baseDay
        return self.get_newuser_bitmap(date, 'mnu').count()

    def get_mru(self, date=None):
        if not date:
            date = self.baseDay
        return self._make_bitmap(date, 'mru').count()

    def list_dau(self, fday=None, tday=None):
        """
        return a list of daily active user's number from fday to tday
        list_dau(string, string) -> [(date1, number),(date2, number)....]
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, map(self.get_dau, dayList))

    def list_dnu(self, fday=None, tday=None):
        """
        return a list of daily new user count from fday to tday
        list_dnu(string, string) -> [(date1, number),(date2, number)....]
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, map(self.get_dnu, dayList))

    def list_dru(self, fday=None, tday=None):
        """
        return a list of daily recharge user from fday to tday
        list_dru(string, string) -> [(date1, number),(date2, number)....]
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, map(self.get_dru, dayList))

    def list_mau(self, fday, tday):
        """
        month active user count
        list_mau(string, string) -> [(datetime1, int),(datetime2,int),....]
        """
        lMonth = util.month1stdate(fday, tday)
        return zip(lMonth, map(self.get_mau, lMonth))

    def list_mnu(self, fday, tday):
        """
        monthly new user count
        list_mnu(string, string) -> [(datetime1, int),(datetime2,int),....]
        """
        lMonth = util.month1stdate(fday, tday)
        return zip(lMonth, map(self.get_mnu, lMonth))

    def list_mru(self, fday, tday):
        """
        monthly rechange user count
        list_mnu(string, string) -> [(datetime1, int),(datetime2,int),....]
        """
        lMonth = util.month1stdate(fday, tday)
        return zip(lMonth, map(self.get_mru, lMonth))

    def mau(self, fday=None, tday=None):
        """
        return the Merged Active Users count from fday to tday
        """
        dayList = self._list_day(fday, tday)
        BaseBM = self._make_bitmap()
        for day in dayList:
            BaseBM.merge(self._make_bitmap(day))
        return BaseBM.count()

    def get_30days_mau(self):
        """
        return the merged active user number in the last 30 days before
        self.baseDay
        """
        fday = self.baseDay - timedelta(days=30)
        return self.mau(fday=fday, tday=self.baseDay)

    def get_7days_mau(self):
        """
        return the last 7 days' active user number before baseDay
        """
        fday = self.baseDay - timedelta(days=7)
        return self.mau(fday=fday, tday=self.baseDay)

    def list_1day_renu(self, fday, tday):
        """
        return the next day's new user retained
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, [self._get_ndays_renu(d, 1) for d in dayList])

    def list_7day_renu(self, fday, tday):
        """
        return the seventh day's new user retained
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, [self._get_ndays_renu(d, 7) for d in dayList])

    def list_30day_renu(self, fday, tday):
        """
        return the thirtieth day's new user retained
        """
        dayList = self._list_day(fday, tday)
        return zip(dayList, [self._get_ndays_renu(d, 30) for d in dayList])

    def _get_ndays_renu(self, day, num):
        return self.get_newuser_bitmap(day)._and_count(
            self.make_bitmap(day + timedelta(days=num)))

    def retained(self, day):
        """
        return the retained user number of baseDay in the givend day
        """
        bm = self._make_bitmap(day)
        return self.baseBitmap.retained(bm)

    def get_retained(self, fday, tday):
        """
        the self.baseday's daily retained number from fday to tday
        """
        dayList = self._list_day(fday, tday)
        return zip(
            dayList,
            self.baseBitmap.retained_count(
                (self._make_bitmap(day) for day in dayList)))

    def daily_retained_list(self, fday, tday):
        """
        the fday's retained number from fday to today
        """
        dayList = self._list_day(fday, tday)
        return zip(
            dayList,
            self.make_bitmap(dayList[0], 'dau').retained_count(
                (self.make_bitmap(day, 'dau') for day in dayList)))

    def customized_retained_list(self, base_day, day_list=[]):
        """
        the  day_list's retained number from fday to today
        :param base_day: the base day
        :param day_list: eg :[datetime,datetime], should not contain base_day
        :return:
        """
        auBitmap = self.make_bitmap(base_day, 'dau')
        return [(base_day, auBitmap.count())] + \
               zip(day_list, self._retained_value(base_day, day_list, 'dau'))

    def get_month_retained(self, fday, tday):
        """
        monthly retained au count from fday's month to tday's month
        """
        lMdates1 = util.month1stdate(fday, tday)
        return zip(
            lMdates1,
            self.make_bitmap(lMdates1[0], 'mau').retained_count(
                (self._make_bitmap(date, 'mau') for date in lMdates1)))

    def get_retained_nu(self, fday, tday):
        """
        return the list of newuser retained number and the date string
        """
        dayList = self._list_day(fday, tday)
        if not self.newUserBitmap:
            self.newUserBitmap = self.get_newuser_bitmap(self.baseDay)
        # logging.info('self.nUB: %s', self.newUserBitmap.count())
        return zip(
            dayList,
            self.newUserBitmap.retained_count(
                (self.make_bitmap(day) for day in dayList)))

    def daily_nu_retained_list(self, fday, tday):
        """
        fday's newuser retained number from fday to tday
        """
        dayList = self._list_day(fday, tday)
        nuBitmap = self.get_newuser_bitmap(dayList[0])
        return [[dayList.pop(0), nuBitmap.count()]] + zip(
            dayList,
            nuBitmap.retained_count(
                (self.make_bitmap(day, 'dau') for day in dayList)))

    def customized_nu_retained_list(self, base_day, day_list=[]):
        """
        the day_list's retained number
        :param base_day: the base day
        :param day_list: eg :[datetime, datetime], should not contain base_day
        :return:
        """
        nuBitmap = self.get_newuser_bitmap(base_day)
        return [(base_day, nuBitmap.count())] + zip(
            day_list, self._retained_value(base_day, day_list, 'dnu'))

    def get_month_retained_nu(self, fday, tday):
        """
        Monthly newuser retained count from fday's month to tday's month
        """
        lMdates1 = util.month1stdate(fday, tday)
        MnuBitmap = self.get_newuser_bitmap(lMdates1[0], 'mnu')
        # logging.info('Newusers count: %s', MnuBitmap.count())
        return [[lMdates1.pop(0), MnuBitmap.count()]] + zip(
            lMdates1,
            MnuBitmap.retained_count(
                (self._make_bitmap(date, 'mau') for date in lMdates1)))

    def retained_by_daylist(self, dayList):
        return zip(
            dayList,
            self.baseBitmap.retained_count(
                (self._make_bitmap(day) for day in dayList)))

    def retained_nu_by_daylist(self, dayList):
        return zip(
            dayList,
            self.newUserBitmap.retained_count(
                (self._make_bitmap(day) for day in dayList)))

    def _retained_value(self, day, day_list, Type='dau'):
        retained_list = []
        if Type == 'dau':
            day_bitmap = self.make_bitmap(day, Type)
        elif Type == 'dnu':
            day_bitmap = self.get_newuser_bitmap(day)

        for t_day in day_list:
            retained_list.append(
                day_bitmap._and_count(self.make_bitmap(t_day, 'dau')))
        return retained_list