n_blobs = self.calc_n_blobs(blob_dim)<EOL>if n_blob > n_blobs or n_blob < <NUM_LIT:0>:<EOL><INDENT>raise ValueError('<STR_LIT>'%(n_blob,n_blobs))<EOL><DEDENT>if blob_dim[self.time_axis]*(n_blob+<NUM_LIT:1>) > self.selection_shape[self.time_axis]:<EOL><INDENT>updated_blob_dim = (int(self.selection_shape[self.time_axis] - blob_dim[self.time_axis]*n_blob), <NUM_LIT:1>, int(blob_dim[self.freq_axis]))<EOL><DEDENT>else:<EOL><INDENT>updated_blob_dim = [int(i) for i in blob_dim]<EOL><DEDENT>blob_start = self._find_blob_start()<EOL>blob = np.zeros(updated_blob_dim, dtype=self._d_type)<EOL>if self.f_start == self.f_begin and self.f_stop == self.f_end:<EOL><INDENT>blob_flat_size = np.prod(blob_dim)<EOL>updated_blob_flat_size = np.prod(updated_blob_dim)<EOL>with open(self.filename, '<STR_LIT:rb>') as f:<EOL><INDENT>f.seek(int(self.idx_data + self._n_bytes  * (blob_start + n_blob*blob_flat_size)))<EOL>dd = np.fromfile(f, count=updated_blob_flat_size, dtype=self._d_type)<EOL><DEDENT>if dd.shape[<NUM_LIT:0>] == updated_blob_flat_size:<EOL><INDENT>blob = dd.reshape(updated_blob_dim)<EOL><DEDENT>else:<EOL><INDENT>logger.info('<STR_LIT>')<EOL>blob = dd.reshape((int(dd.shape[<NUM_LIT:0>]/blob_dim[self.freq_axis]),blob_dim[self.beam_axis],blob_dim[self.freq_axis]))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>for blobt in range(updated_blob_dim[self.time_axis]):<EOL><INDENT>with open(self.filename, '<STR_LIT:rb>') as f:<EOL><INDENT>f.seek(int(self.idx_data + self._n_bytes * (blob_start + n_blob*blob_dim[self.time_axis]*self.n_channels_in_file + blobt*self.n_channels_in_file)))<EOL>dd = np.fromfile(f, count=blob_dim[self.freq_axis], dtype=self._d_type)<EOL><DEDENT>blob[blobt] = dd<EOL>


read all the data.
            If reverse=True the x axis is flipped.


raise NotImplementedError('<STR_LIT>')<EOL>self.filfile.seek(int(self.datastart+self.channels*rownumber*(int(self.nbits/<NUM_LIT:8>))))<EOL>data=np.fromfile(self.filfile,count=self.channels,dtype=self.dtype).reshape(<NUM_LIT:1>, self.channels)<EOL>if reverse:<EOL><INDENT>data = data[:,::-<NUM_LIT:1>]<EOL><DEDENT>return data<EOL>

Read a block of data. The number of samples per row is set in self.channels
            If reverse=True the x axis is flipped.


raise NotImplementedError('<STR_LIT>')<EOL>self.filfile.seek(int(self.datastart+self.channels*rownumber*(int(self.nbits/<NUM_LIT:8>))))<EOL>data=np.fromfile(self.filfile,count=self.channels*n_rows,dtype=self.dtype).reshape(n_rows, self.channels)<EOL>if reverse:<EOL><INDENT>data = data[:,::-<NUM_LIT:1>]<EOL><DEDENT>return data<EOL>


from argparse import ArgumentParser<EOL>if not HAS_BITSHUFFLE:<EOL><INDENT>print("<STR_LIT>")<EOL>exit()<EOL><DEDENT>parser = ArgumentParser(description="<STR_LIT>")<EOL>parser.add_argument('<STR_LIT:filename>', type=str, help='<STR_LIT>')<EOL>args = parser.parse_args()<EOL>fileroot = args.filename.split('<STR_LIT>')[<NUM_LIT:0>]<EOL>filelist = glob.glob(fileroot + '<STR_LIT>')<EOL>filelist = sorted(filelist)<EOL>r = GuppiRaw(filelist[<NUM_LIT:0>])<EOL>header, data = r.read_next_data_block()<EOL>dshape = data.shape <EOL>print(dshape)<EOL>n_blocks_total = <NUM_LIT:0><EOL>for filename in filelist:<EOL><INDENT>print(filename)<EOL>r = GuppiRaw(filename)<EOL>n_blocks_total += r.n_blocks<EOL><DEDENT>print(n_blocks_total)<EOL>full_dshape = np.concatenate(((n_blocks_total,), dshape))<EOL>h5 = h5py.File(fileroot + '<STR_LIT>', '<STR_LIT:w>')<EOL>h5.attrs['<STR_LIT>'] = '<STR_LIT>'<EOL>block_size = <NUM_LIT:0>      <EOL>dset = h5.create_dataset('<STR_LIT:data>',<EOL>shape=full_dshape,<EOL>dtype=data.dtype) <EOL>h5_idx = <NUM_LIT:0><EOL>for filename in filelist:<EOL><INDENT>print("<STR_LIT>" % filename)<EOL>r = GuppiRaw(filename)<EOL>h5 = h5py.File(filename + '<STR_LIT>', '<STR_LIT:w>')<EOL>header, data = r.read_next_data_block()<EOL>for ii in range(<NUM_LIT:0>, r.n_blocks):<EOL><INDENT>t0 = time.time()<EOL>print("<STR_LIT>" % (h5_idx+<NUM_LIT:1>, full_dshape[<NUM_LIT:0>]))<EOL>header, data = r.read_next_data_block()<EOL>t1 = time.time()<EOL>t2 = time.time()<EOL>print("<STR_LIT>" % (h5_idx+<NUM_LIT:1>, full_dshape[<NUM_LIT:0>]))<EOL>dset[h5_idx, :] = data<EOL>t3 = time.time()<EOL>print("<STR_LIT>" % ((t1-t0), (t3-t2)))<EOL>h5_idx += <NUM_LIT:1><EOL>for key, value in header.items():<EOL><INDENT>dset.attrs[key] = value<EOL><DEDENT><DEDENT>h5.close()<EOL>t1 = time.time()<EOL>print("<STR_LIT>" % (t1- t0))<EOL><DEDENT>

Command line tool for converting guppi raw into HDF5 versions of guppi raw


with  open(filename, '<STR_LIT:rb>') as f:<EOL><INDENT>header_sub_count = <NUM_LIT:0><EOL>eoh_found = False<EOL>while not eoh_found:<EOL><INDENT>header_sub = f.read(<NUM_LIT>)<EOL>header_sub_count += <NUM_LIT:1><EOL>if b'<STR_LIT>' in header_sub:<EOL><INDENT>idx_end = header_sub.index(b'<STR_LIT>') + len(b'<STR_LIT>')<EOL>eoh_found = True<EOL>break<EOL><DEDENT><DEDENT>idx_end = (header_sub_count -<NUM_LIT:1>) * <NUM_LIT> + idx_end<EOL><DEDENT>return idx_end<EOL>

Return the length of the blimpy header, in bytes

    Args:
        filename (str): name of file to open

    Returns:
        idx_end (int): length of header, in bytes


n_bytes = np.fromstring(fh.read(<NUM_LIT:4>), dtype='<STR_LIT>')[<NUM_LIT:0>]<EOL>if n_bytes > <NUM_LIT:255>:<EOL><INDENT>n_bytes = <NUM_LIT:16><EOL><DEDENT>keyword = fh.read(n_bytes)<EOL>if keyword == b'<STR_LIT>' or keyword == b'<STR_LIT>':<EOL><INDENT>return keyword, <NUM_LIT:0>, fh.tell()<EOL><DEDENT>else:<EOL><INDENT>dtype = header_keyword_types[keyword]<EOL>idx = fh.tell()<EOL>if dtype == b'<STR_LIT>':<EOL><INDENT>val = struct.unpack(dtype, fh.read(<NUM_LIT:4>))[<NUM_LIT:0>]<EOL><DEDENT>if dtype == b'<STR_LIT>':<EOL><INDENT>val = struct.unpack(dtype, fh.read(<NUM_LIT:8>))[<NUM_LIT:0>]<EOL><DEDENT>if dtype == b'<STR_LIT:str>':<EOL><INDENT>str_len = np.fromstring(fh.read(<NUM_LIT:4>), dtype='<STR_LIT>')[<NUM_LIT:0>]<EOL>val = fh.read(str_len)<EOL><DEDENT>if dtype == b'<STR_LIT>':<EOL><INDENT>val = struct.unpack('<STR_LIT>', fh.read(<NUM_LIT:8>))[<NUM_LIT:0>]<EOL>val = fil_double_to_angle(val)<EOL>if keyword == b'<STR_LIT>':<EOL><INDENT>val = Angle(val, unit=u.hour)<EOL><DEDENT>else:<EOL><INDENT>val = Angle(val, unit=u.deg)<EOL><DEDENT><DEDENT>return keyword, val, idx<EOL><DEDENT>

Args:
    fh (file): file handler

Returns:


with open(filename, '<STR_LIT:rb>') as fh:<EOL><INDENT>is_fil = True<EOL>try:<EOL><INDENT>keyword, value, idx = read_next_header_keyword(fh)<EOL>try:<EOL><INDENT>assert keyword == b'<STR_LIT>'<EOL><DEDENT>except AssertionError:<EOL><INDENT>is_fil = False<EOL><DEDENT><DEDENT>except KeyError:<EOL><INDENT>is_fil = False<EOL><DEDENT>return is_fil<EOL><DEDENT>

Open file and confirm if it is a filterbank file or not.


with open(filename, '<STR_LIT:rb>') as fh:<EOL><INDENT>header_dict = {}<EOL>header_idxs = {}<EOL>keyword, value, idx = read_next_header_keyword(fh)<EOL>try:<EOL><INDENT>assert keyword == b'<STR_LIT>'<EOL><DEDENT>except AssertionError:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>while True:<EOL><INDENT>keyword, value, idx = read_next_header_keyword(fh)<EOL>if keyword == b'<STR_LIT>':<EOL><INDENT>break<EOL><DEDENT>else:<EOL><INDENT>header_dict[keyword] = value<EOL>header_idxs[keyword] = idx<EOL><DEDENT><DEDENT><DEDENT>if return_idxs:<EOL><INDENT>return header_idxs<EOL><DEDENT>else:<EOL><INDENT>return header_dict<EOL><DEDENT>

Read blimpy header and return a Python dictionary of key:value pairs

    Args:
        filename (str): name of file to open

    Optional args:
        return_idxs (bool): Default False. If true, returns the file offset indexes
                            for values

    returns


def fix_header(filename, keyword, new_value):

<EOL>hd = read_header(filename)<EOL>hi = read_header(filename, return_idxs=True)<EOL>idx = hi[keyword]<EOL>dtype = header_keyword_types[keyword]<EOL>dtype_to_type = {b'<STR_LIT>'  : np.int32,<EOL>b'<STR_LIT:str>' : bytes,<EOL>b'<STR_LIT>'  : np.float64,<EOL>b'<STR_LIT>' : to_sigproc_angle}<EOL>value_dtype = dtype_to_type[dtype]<EOL>if isinstance(value_dtype, bytes):<EOL><INDENT>if len(hd[keyword]) == len(new_value):<EOL><INDENT>val_str = np.int32(len(new_value)).tostring() + new_value<EOL><DEDENT>else:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT><DEDENT>else:<EOL><INDENT>val_str = value_dtype(new_value).tostring()<EOL><DEDENT>with open(filename, '<STR_LIT>') as fh:<EOL><INDENT>fh.seek(idx)<EOL>fh.write(val_str)<EOL><DEDENT>

Apply a quick patch-up to a Filterbank header by overwriting a header value

    Args:
        filename (str): name of file to open and fix. WILL BE MODIFIED.
        keyword (stt):  header keyword to update
        new_value (long, double, angle or string): New value to write.

    Notes:
        This will overwrite the current value of the blimpy with a desired
        'fixed' version. Note that this has limited support for patching
        string-type values - if the length of the string changes, all hell will
        break loose.


negative = (angle < <NUM_LIT:0.0>)<EOL>angle = np.abs(angle)<EOL>dd = np.floor((angle / <NUM_LIT>))<EOL>angle -= <NUM_LIT> * dd<EOL>mm = np.floor((angle / <NUM_LIT:100>))<EOL>ss = angle - <NUM_LIT:100> * mm<EOL>dd += mm/<NUM_LIT> + ss/<NUM_LIT><EOL>if negative:<EOL><INDENT>dd *= -<NUM_LIT:1><EOL><DEDENT>return dd<EOL>

Reads a little-endian double in ddmmss.s (or hhmmss.s) format and then
    converts to Float degrees (or hours).  This is primarily used to read
    src_raj and src_dej header values.


keyword = bytes(keyword)<EOL>if value is None:<EOL><INDENT>return np.int32(len(keyword)).tostring() + keyword<EOL><DEDENT>else:<EOL><INDENT>dtype = header_keyword_types[keyword]<EOL>dtype_to_type = {b'<STR_LIT>'  : np.int32,<EOL>b'<STR_LIT:str>' : str,<EOL>b'<STR_LIT>'  : np.float64,<EOL>b'<STR_LIT>' : to_sigproc_angle}<EOL>value_dtype = dtype_to_type[dtype]<EOL>if value_dtype is str:<EOL><INDENT>return np.int32(len(keyword)).tostring() + keyword + np.int32(len(value)).tostring() + value<EOL><DEDENT>else:<EOL><INDENT>return np.int32(len(keyword)).tostring() + keyword + value_dtype(value).tostring()<EOL><DEDENT><DEDENT>

Generate a serialized string for a sigproc keyword:value pair

    If value=None, just the keyword will be written with no payload.
    Data type is inferred by keyword name (via a lookup table)

    Args:
        keyword (str): Keyword to write
        value (None, float, str, double or angle): value to write to file

    Returns:
        value_str (str): serialized string to write to file.


header_string = b'<STR_LIT>'<EOL>header_string += to_sigproc_keyword(b'<STR_LIT>')<EOL>for keyword in f.header.keys():<EOL><INDENT>if keyword == b'<STR_LIT>':<EOL><INDENT>header_string += to_sigproc_keyword(b'<STR_LIT>')  + to_sigproc_angle(f.header[b'<STR_LIT>'])<EOL><DEDENT>elif keyword == b'<STR_LIT>':<EOL><INDENT>header_string += to_sigproc_keyword(b'<STR_LIT>')  + to_sigproc_angle(f.header[b'<STR_LIT>'])<EOL><DEDENT>elif keyword == b'<STR_LIT>' or keyword == b'<STR_LIT>':<EOL><INDENT>header_string += to_sigproc_keyword(keyword)  + np.float64(f.header[keyword]).tostring()<EOL><DEDENT>elif keyword not in header_keyword_types.keys():<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>header_string += to_sigproc_keyword(keyword, f.header[keyword])<EOL><DEDENT><DEDENT>header_string += to_sigproc_keyword(b'<STR_LIT>')<EOL>return header_string<EOL>

Generate a serialzed sigproc header which can be written to disk.

    Args:
        f (Filterbank object): Filterbank object for which to generate header

    Returns:
        header_str (str): Serialized string corresponding to header


x = str(angle_val)<EOL>if '<STR_LIT:.>' in x:<EOL><INDENT>if '<STR_LIT:h>' in x:<EOL><INDENT>d, m, s, ss = int(x[<NUM_LIT:0>:x.index('<STR_LIT:h>')]), int(x[x.index('<STR_LIT:h>')+<NUM_LIT:1>:x.index('<STR_LIT:m>')]),int(x[x.index('<STR_LIT:m>')+<NUM_LIT:1>:x.index('<STR_LIT:.>')]), float(x[x.index('<STR_LIT:.>'):x.index('<STR_LIT:s>')])<EOL><DEDENT>if '<STR_LIT:d>' in x:<EOL><INDENT>d, m, s, ss = int(x[<NUM_LIT:0>:x.index('<STR_LIT:d>')]), int(x[x.index('<STR_LIT:d>')+<NUM_LIT:1>:x.index('<STR_LIT:m>')]),int(x[x.index('<STR_LIT:m>')+<NUM_LIT:1>:x.index('<STR_LIT:.>')]), float(x[x.index('<STR_LIT:.>'):x.index('<STR_LIT:s>')])<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if '<STR_LIT:h>' in x:<EOL><INDENT>d, m, s = int(x[<NUM_LIT:0>:x.index('<STR_LIT:h>')]), int(x[x.index('<STR_LIT:h>')+<NUM_LIT:1>:x.index('<STR_LIT:m>')]),int(x[x.index('<STR_LIT:m>')+<NUM_LIT:1>:x.index('<STR_LIT:s>')])<EOL><DEDENT>if '<STR_LIT:d>' in x:<EOL><INDENT>d, m, s = int(x[<NUM_LIT:0>:x.index('<STR_LIT:d>')]), int(x[x.index('<STR_LIT:d>')+<NUM_LIT:1>:x.index('<STR_LIT:m>')]),int(x[x.index('<STR_LIT:m>')+<NUM_LIT:1>:x.index('<STR_LIT:s>')])<EOL><DEDENT>ss = <NUM_LIT:0><EOL><DEDENT>num = str(d).zfill(<NUM_LIT:2>) + str(m).zfill(<NUM_LIT:2>) + str(s).zfill(<NUM_LIT:2>)+ '<STR_LIT:.>' + str(ss).split("<STR_LIT:.>")[-<NUM_LIT:1>]<EOL>return np.float64(num).tostring()<EOL>

Convert an astropy.Angle to the ridiculous sigproc angle format string.


<EOL>h = read_header(filename)<EOL>n_bytes  = int(h[b'<STR_LIT>'] / <NUM_LIT:8>)<EOL>n_chans = h[b'<STR_LIT>']<EOL>n_ifs   = h[b'<STR_LIT>']<EOL>idx_data = len_header(filename)<EOL>f = open(filename, '<STR_LIT:rb>')<EOL>f.seek(idx_data)<EOL>filesize = os.path.getsize(filename)<EOL>n_bytes_data = filesize - idx_data<EOL>if h[b'<STR_LIT>'] == <NUM_LIT:2>:<EOL><INDENT>n_ints = int(<NUM_LIT:4> * n_bytes_data / (n_chans * n_ifs))<EOL><DEDENT>else:<EOL><INDENT>n_ints = int(n_bytes_data / (n_bytes * n_chans * n_ifs))<EOL><DEDENT>return n_ints<EOL>

Calculate number of integrations in a given file


return <NUM_LIT:10> * np.log10(x)<EOL>


return <NUM_LIT> ** (x / <NUM_LIT>)<EOL>


idx_closest = np.argmin(np.abs(np.array(xarr) - val))<EOL>return idx_closest<EOL>

Return the index of the closest in xarr to value val


if d.ndim == <NUM_LIT:2>:<EOL><INDENT>if n_y is None:<EOL><INDENT>n_y = <NUM_LIT:1><EOL><DEDENT>if n_x is None:<EOL><INDENT>n_x = <NUM_LIT:1><EOL><DEDENT>d = d[:int(d.shape[<NUM_LIT:0>] // n_x) * n_x, :int(d.shape[<NUM_LIT:1>] // n_y) * n_y]<EOL>d = d.reshape((d.shape[<NUM_LIT:0>] // n_x, n_x, d.shape[<NUM_LIT:1>] // n_y, n_y))<EOL>d = d.mean(axis=<NUM_LIT:3>)<EOL>d = d.mean(axis=<NUM_LIT:1>)<EOL><DEDENT>elif d.ndim == <NUM_LIT:1>:<EOL><INDENT>d = d[:int(d.shape[<NUM_LIT:0>] // n_x) * n_x]<EOL>d = d.reshape((d.shape[<NUM_LIT:0>] // n_x, n_x))<EOL>d = d.mean(axis=<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>return d<EOL>

Rebin data by averaging bins together

    Args:
    d (np.array): data
    n_x (int): number of bins in x dir to rebin into one
    n_y (int): number of bins in y dir to rebin into one

    Returns:
    d: rebinned data with shape (n_x, n_y)


if nbit > <NUM_LIT:8>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if <NUM_LIT:8> % nbit != <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if data.dtype not in (np.uint8, np.int8):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>if nbit == <NUM_LIT:8>:<EOL><INDENT>return data<EOL><DEDENT>elif nbit == <NUM_LIT:4>:<EOL><INDENT>data = unpack_4to8(data)<EOL>return data<EOL><DEDENT>elif nbit == <NUM_LIT:2>:<EOL><INDENT>data = unpack_2to8(data)<EOL>return data<EOL><DEDENT>elif nbit == <NUM_LIT:1>:<EOL><INDENT>data = unpack_1to8(data)<EOL>return data<EOL><DEDENT>

upgrade data from nbits to 8bits

    Notes: Pretty sure this function is a little broken!


return np.unpackbits(data)<EOL>

Promote 1-bit unisgned data into 8-bit unsigned data.

    Args:
        data: Numpy array with dtype == uint8


two_eight_lookup = {<NUM_LIT:0>: <NUM_LIT>,<EOL><NUM_LIT:1>: <NUM_LIT:12>,<EOL><NUM_LIT:2>: -<NUM_LIT:12>,<EOL><NUM_LIT:3>: -<NUM_LIT>}<EOL>tmp = data.astype(np.uint32)<EOL>tmp = (tmp | (tmp << <NUM_LIT:12>)) & <NUM_LIT><EOL>tmp = (tmp | (tmp << <NUM_LIT:6>)) & <NUM_LIT><EOL>tmp = tmp.byteswap()<EOL>tmp = tmp.view('<STR_LIT>')<EOL>mapped = np.array(tmp, dtype=np.int8)<EOL>for k, v in two_eight_lookup.items():<EOL><INDENT>mapped[tmp == k] = v<EOL><DEDENT>return mapped<EOL>

Promote 2-bit unisgned data into 8-bit unsigned data.

    Args:
        data: Numpy array with dtype == uint8

    Notes:
        DATA MUST BE LOADED as np.array() with dtype='uint8'.

        This works with some clever shifting and AND / OR operations.
        Data is LOADED as 8-bit, then promoted to 32-bits:
        /ABCD EFGH/ (8 bits of data)
        /0000 0000/0000 0000/0000 0000/ABCD EFGH/ (8 bits of data as a 32-bit word)

        Once promoted, we can do some shifting, AND and OR operations:
        /0000 0000/0000 ABCD/EFGH 0000/0000 0000/ (shifted << 12)
        /0000 0000/0000 ABCD/EFGH 0000/ABCD EFGH/ (bitwise OR of previous two lines)
        /0000 0000/0000 ABCD/0000 0000/0000 EFGH/ (bitwise AND with mask 0xF000F)
        /0000 00AB/CD00 0000/0000 00EF/GH00 0000/ (prev. line shifted << 6)
        /0000 00AB/CD00 ABCD/0000 00EF/GH00 EFGH/ (bitwise OR of previous two lines)
        /0000 00AB/0000 00CD/0000 00EF/0000 00GH/ (bitwise AND with 0x3030303)

        Then we change the view of the data to interpret it as 4x8 bit:
        [000000AB, 000000CD, 000000EF, 000000GH]  (change view from 32-bit to 4x8-bit)

        The converted bits are then mapped to values in the range [-40, 40] according to a lookup chart.
        The mapping is based on specifications in the breakthough docs:
        https://github.com/UCBerkeleySETI/breakthrough/blob/master/doc/RAW-File-Format.md


tmpdata = data.astype(np.int16)  <EOL>tmpdata = (tmpdata | (tmpdata << <NUM_LIT:4>)) & <NUM_LIT><EOL>updata = tmpdata.byteswap()<EOL>return updata.view(data.dtype)<EOL>

Promote 2-bit unisgned data into 8-bit unsigned data.

    Args:
        data: Numpy array with dtype == uint8

    Notes:
        # The process is this:
        # ABCDEFGH [Bits of one 4+4-bit value]
        # 00000000ABCDEFGH [astype(uint16)]
        # 0000ABCDEFGH0000 [<< 4]
        # 0000ABCDXXXXEFGH [bitwise 'or' of previous two lines]
        # 0000111100001111 [0x0F0F]
        # 0000ABCD0000EFGH [bitwise 'and' of previous two lines]
        # ABCD0000EFGH0000 [<< 4]
        # which effectively pads the two 4-bit values with zeros on the right
        # Note: This technique assumes LSB-first ordering


from argparse import ArgumentParser<EOL>parser = ArgumentParser(description="<STR_LIT>")<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store>',  default='<STR_LIT>', dest='<STR_LIT>', type=str,<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT:filename>', type=str,<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store>', default=None, dest='<STR_LIT>', type=float,<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store>', default=None, dest='<STR_LIT>', type=float,<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store>', default=None, dest='<STR_LIT>', type=int,<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store>', default=None, dest='<STR_LIT>', type=int,<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store_true>', default=False, dest='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store_true>', default=False, dest='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store>', default='<STR_LIT>', dest='<STR_LIT>', type=str,<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT:store_true>', default=False, dest='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT>', action='<STR_LIT>', default=True, dest='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>parser.add_argument('<STR_LIT:-c>', action='<STR_LIT:store_true>', default=False, dest='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>args = parser.parse_args()<EOL>filename = args.filename<EOL>load_data = not args.info_only<EOL>wtp = args.what_to_plot<EOL>if not wtp or '<STR_LIT:s>' in wtp:<EOL><INDENT>if args.t_start == None:<EOL><INDENT>t_start = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>t_start = args.t_start<EOL><DEDENT>t_stop  = t_start + <NUM_LIT:1><EOL>if args.average:<EOL><INDENT>t_start = None<EOL>t_stop  = None<EOL><DEDENT><DEDENT>else:<EOL><INDENT>t_start = args.t_start<EOL>t_stop  = args.t_stop<EOL><DEDENT>if args.info_only:<EOL><INDENT>args.blank_dc = False<EOL>args.calibrate_band_pass = False<EOL><DEDENT>fil = Filterbank(filename, f_start=args.f_start, f_stop=args.f_stop,<EOL>t_start=t_start, t_stop=t_stop,<EOL>load_data=load_data,blank_dc=args.blank_dc,<EOL>cal_band_pass=args.calibrate_band_pass)<EOL>fil.info()<EOL>if not args.info_only:<EOL><INDENT>if args.what_to_plot == "<STR_LIT:w>":<EOL><INDENT>plt.figure("<STR_LIT>", figsize=(<NUM_LIT:8>, <NUM_LIT:6>))<EOL>fil.plot_waterfall(f_start=args.f_start, f_stop=args.f_stop)<EOL><DEDENT>elif args.what_to_plot == "<STR_LIT:s>":<EOL><INDENT>plt.figure("<STR_LIT>", figsize=(<NUM_LIT:8>, <NUM_LIT:6>))<EOL>fil.plot_spectrum(logged=True, f_start=args.f_start, f_stop=args.f_stop, t='<STR_LIT:all>')<EOL><DEDENT>elif args.what_to_plot == "<STR_LIT>":<EOL><INDENT>plt.figure("<STR_LIT>", figsize=(<NUM_LIT:8>, <NUM_LIT:6>))<EOL>fil.plot_spectrum_min_max(logged=True, f_start=args.f_start, f_stop=args.f_stop, t='<STR_LIT:all>')<EOL><DEDENT>elif args.what_to_plot == "<STR_LIT:k>":<EOL><INDENT>plt.figure("<STR_LIT>", figsize=(<NUM_LIT:8>, <NUM_LIT:6>))<EOL>fil.plot_kurtosis(f_start=args.f_start, f_stop=args.f_stop)<EOL><DEDENT>elif args.what_to_plot == "<STR_LIT:t>":<EOL><INDENT>plt.figure("<STR_LIT>", figsize=(<NUM_LIT:8>, <NUM_LIT:6>))<EOL>fil.plot_time_series(f_start=args.f_start, f_stop=args.f_stop,orientation='<STR_LIT:h>')<EOL><DEDENT>elif args.what_to_plot == "<STR_LIT:a>":<EOL><INDENT>plt.figure("<STR_LIT>", figsize=(<NUM_LIT:12>, <NUM_LIT:9>),facecolor='<STR_LIT>')<EOL>fil.plot_all(logged=True, f_start=args.f_start, f_stop=args.f_stop, t='<STR_LIT:all>')<EOL><DEDENT>elif args.what_to_plot == "<STR_LIT>":<EOL><INDENT>plt.figure("<STR_LIT>", figsize=(<NUM_LIT:12>, <NUM_LIT:9>),facecolor='<STR_LIT>')<EOL>fil.plot_all(logged=True, f_start=args.f_start, f_stop=args.f_stop, t='<STR_LIT:all>',kurtosis=False)<EOL><DEDENT>if args.plt_filename != '<STR_LIT>':<EOL><INDENT>plt.savefig(args.plt_filename)<EOL><DEDENT>if not args.save_only:<EOL><INDENT>if '<STR_LIT>' in os.environ.keys():<EOL><INDENT>plt.show()<EOL><DEDENT>else:<EOL><INDENT>print("<STR_LIT>")<EOL><DEDENT><DEDENT><DEDENT>

Command line tool for plotting and viewing info on filterbank files


def __init__(self, filename=None, f_start=None, f_stop=None,<EOL>t_start=None, t_stop=None, load_data=True,<EOL>header_dict=None, data_array=None, blank_dc=False,cal_band_pass=False):

if filename:<EOL><INDENT>self.filename = filename<EOL>if HAS_HDF5:<EOL><INDENT>if h5py.is_hdf5(filename):<EOL><INDENT>self.read_hdf5(filename, f_start, f_stop, t_start, t_stop, load_data)<EOL><DEDENT>else:<EOL><INDENT>self.read_filterbank(filename, f_start, f_stop, t_start, t_stop, load_data)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self.read_filterbank(filename, f_start, f_stop, t_start, t_stop, load_data)<EOL><DEDENT><DEDENT>elif header_dict is not None and data_array is not None:<EOL><INDENT>self.filename = b'<STR_LIT>'<EOL>self.header = header_dict<EOL>self.data = data_array<EOL>self.n_ints_in_file = <NUM_LIT:0><EOL>self._setup_freqs()<EOL><DEDENT>else:<EOL><INDENT>pass<EOL><DEDENT>if blank_dc:<EOL><INDENT>print("<STR_LIT>")<EOL>n_coarse_chan = self.calc_n_coarse_chan()<EOL>self.blank_dc(n_coarse_chan)<EOL><DEDENT>if cal_band_pass:<EOL><INDENT>print("<STR_LIT>")<EOL>self.calibrate_band_pass_N1()<EOL><DEDENT>

Class for loading and plotting blimpy data.

        This class parses the blimpy file and stores the header and data
        as objects:
            fb = Filterbank('filename_here.fil')
            fb.header        # blimpy header, as a dictionary
            fb.data          # blimpy data, as a numpy array

        Args:
            filename (str): filename of blimpy file.
            f_start (float): start frequency in MHz
            f_stop (float): stop frequency in MHz
            t_start (int): start integration ID
            t_stop (int): stop integration ID
            load_data (bool): load data. If set to False, only header will be read.
            header_dict (dict): Create blimpy from header dictionary + data array
            data_array (np.array): Create blimpy from header dict + data array
            blank_dc (bool): Blanks the DC bin or not.


def read_hdf5(self, filename, f_start=None, f_stop=None,<EOL>t_start=None, t_stop=None, load_data=True):

print("<STR_LIT>")<EOL><INDENT>raise DeprecationWarning('<STR_LIT>')<EOL><DEDENT>self.header = {}<EOL>self.filename = filename<EOL>self.h5 = h5py.File(filename)<EOL>for key, val in self.h5[b'<STR_LIT:data>'].attrs.items():<EOL><INDENT>if six.PY3:<EOL><INDENT>key = bytes(key, '<STR_LIT:ascii>')<EOL><DEDENT>if key == b'<STR_LIT>':<EOL><INDENT>self.header[key] = Angle(val, unit='<STR_LIT>')<EOL><DEDENT>elif key == b'<STR_LIT>':<EOL><INDENT>self.header[key] = Angle(val, unit='<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>self.header[key] = val<EOL><DEDENT><DEDENT>self.n_ints_in_file = self.h5[b"<STR_LIT:data>"].shape[<NUM_LIT:0>]<EOL>i_start, i_stop, chan_start_idx, chan_stop_idx = self._setup_freqs(f_start=f_start, f_stop=f_stop)<EOL>ii_start, ii_stop, n_ints = self._setup_time_axis(t_start=t_start, t_stop=t_stop)<EOL>if load_data:<EOL><INDENT>self.data = self.h5[b"<STR_LIT:data>"][ii_start:ii_stop, :, chan_start_idx:chan_stop_idx]<EOL>self.file_size_bytes = os.path.getsize(self.filename)<EOL>

Populate Filterbank instance with data from HDF5 file

        Note:
            This is to be deprecated in future, please use Waterfall() to open files.


def _setup_freqs(self, f_start=None, f_stop=None):

<EOL>f0 = self.header[b'<STR_LIT>']<EOL>f_delt = self.header[b'<STR_LIT>']<EOL>i_start, i_stop = <NUM_LIT:0>, self.header[b'<STR_LIT>']<EOL>if f_start:<EOL><INDENT>i_start = int((f_start - f0) / f_delt)<EOL><DEDENT>if f_stop:<EOL><INDENT>i_stop  = int((f_stop - f0)  / f_delt)<EOL><DEDENT>chan_start_idx = np.int(i_start)<EOL>chan_stop_idx  = np.int(i_stop)<EOL>if i_start < i_stop:<EOL><INDENT>i_vals = np.arange(chan_start_idx, chan_stop_idx)<EOL><DEDENT>else:<EOL><INDENT>i_vals = np.arange(chan_stop_idx, chan_start_idx)<EOL><DEDENT>self.freqs = f_delt * i_vals + f0<EOL><INDENT>if f_delt < <NUM_LIT:0>:<EOL><INDENT>self.freqs = self.freqs[::-<NUM_LIT:1>]<EOL><DEDENT><DEDENT>if chan_stop_idx < chan_start_idx:<EOL><INDENT>chan_stop_idx, chan_start_idx = chan_start_idx,chan_stop_idx<EOL><DEDENT>return i_start, i_stop, chan_start_idx, chan_stop_idx<EOL>


def _setup_time_axis(self, t_start=None, t_stop=None):

<EOL>ii_start, ii_stop = <NUM_LIT:0>, self.n_ints_in_file<EOL>if t_start:<EOL><INDENT>ii_start = t_start<EOL><DEDENT>if t_stop:<EOL><INDENT>ii_stop = t_stop<EOL><DEDENT>n_ints = ii_stop - ii_start<EOL>t0 = self.header[b'<STR_LIT>']<EOL>t_delt = self.header[b'<STR_LIT>']<EOL>self.timestamps = np.arange(<NUM_LIT:0>, n_ints) * t_delt / <NUM_LIT>/<NUM_LIT>/<NUM_LIT> + t0<EOL>return ii_start, ii_stop, n_ints<EOL>


def read_filterbank(self, filename=None, f_start=None, f_stop=None,<EOL>t_start=None, t_stop=None, load_data=True):

if filename is None:<EOL><INDENT>filename = self.filename<EOL><DEDENT>else:<EOL><INDENT>self.filename = filename<EOL><DEDENT>self.header = read_header(filename)<EOL>i_start, i_stop, chan_start_idx, chan_stop_idx = self._setup_freqs(f_start=f_start, f_stop=f_stop)<EOL>n_bits  = self.header[b'<STR_LIT>']<EOL>n_bytes  = int(self.header[b'<STR_LIT>'] / <NUM_LIT:8>)<EOL>n_chans = self.header[b'<STR_LIT>']<EOL>n_chans_selected = self.freqs.shape[<NUM_LIT:0>]<EOL>n_ifs   = self.header[b'<STR_LIT>']<EOL>self.idx_data = len_header(filename)<EOL>f = open(filename, '<STR_LIT:rb>')<EOL>f.seek(self.idx_data)<EOL>filesize = os.path.getsize(self.filename)<EOL>n_bytes_data = filesize - self.idx_data<EOL>self.n_ints_in_file  = calc_n_ints_in_file(self.filename)<EOL>self.file_size_bytes = filesize<EOL>ii_start, ii_stop, n_ints = self._setup_time_axis(t_start=t_start, t_stop=t_stop)<EOL>f.seek(int(ii_start * n_bits * n_ifs * n_chans / <NUM_LIT:8>), <NUM_LIT:1>)<EOL>i0 = np.min((chan_start_idx, chan_stop_idx))<EOL>i1 = np.max((chan_start_idx, chan_stop_idx))<EOL>if n_bits == <NUM_LIT:2>:<EOL><INDENT>dd_type = b'<STR_LIT>'<EOL>n_chans_selected = int(n_chans_selected/<NUM_LIT:4>)<EOL><DEDENT>elif n_bytes == <NUM_LIT:4>:<EOL><INDENT>dd_type = b'<STR_LIT>'<EOL><DEDENT>elif n_bytes == <NUM_LIT:2>:<EOL><INDENT>dd_type = b'<STR_LIT>'<EOL><DEDENT>elif n_bytes == <NUM_LIT:1>:<EOL><INDENT>dd_type = b'<STR_LIT>'<EOL><DEDENT>if load_data:<EOL><INDENT>if n_ints * n_ifs * n_chans_selected > MAX_DATA_ARRAY_SIZE:<EOL><INDENT>print("<STR_LIT>")<EOL>sys.exit()<EOL><DEDENT>if n_bits == <NUM_LIT:2>:<EOL><INDENT>self.data = np.zeros((n_ints, n_ifs, n_chans_selected*<NUM_LIT:4>), dtype=dd_type)<EOL><DEDENT>else:<EOL><INDENT>self.data = np.zeros((n_ints, n_ifs, n_chans_selected), dtype=dd_type)<EOL><DEDENT>for ii in range(n_ints):<EOL><INDENT>"""<STR_LIT>"""<EOL>for jj in range(n_ifs):<EOL><INDENT>f.seek(n_bytes * i0, <NUM_LIT:1>) <EOL>dd = np.fromfile(f, count=n_chans_selected, dtype=dd_type)<EOL><INDENT>if f_delt < <NUM_LIT:0>:<EOL><INDENT>dd = dd[::-<NUM_LIT:1>]<EOL><DEDENT><DEDENT>if n_bits == <NUM_LIT:2>:<EOL><INDENT>dd = unpack_2to8(dd)<EOL><DEDENT>self.data[ii, jj] = dd<EOL>f.seek(n_bytes * (n_chans - i1), <NUM_LIT:1>)  <EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>print("<STR_LIT>")<EOL>self.data = np.array([<NUM_LIT:0>], dtype=dd_type)<EOL><DEDENT>

Populate Filterbank instance with data from Filterbank file

        Note:
            This is to be deprecated in future, please use Waterfall() to open files.


if self.header[b'<STR_LIT>'] == <NUM_LIT:6>:<EOL><INDENT>self.coords = gbt_coords<EOL><DEDENT>elif self.header[b'<STR_LIT>'] == <NUM_LIT:4>:<EOL><INDENT>self.coords = parkes_coords<EOL><DEDENT>else:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>if HAS_SLALIB:<EOL><INDENT>dut1 = <NUM_LIT:0.0><EOL>mjd = self.header[b'<STR_LIT>']<EOL>tellong = np.deg2rad(self.coords[<NUM_LIT:1>])<EOL>last = s.sla_gmst(mjd) - tellong + s.sla_eqeqx(mjd) + dut1<EOL>if last < <NUM_LIT:0.0> : last = last + <NUM_LIT>*np.pi<EOL>return last<EOL><DEDENT>else:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>


ra = Angle(self.header[b'<STR_LIT>'], unit='<STR_LIT>')<EOL>dec = Angle(self.header[b'<STR_LIT>'], unit='<STR_LIT>')<EOL>mjdd = self.header[b'<STR_LIT>']<EOL>rarad = ra.to('<STR_LIT>').value<EOL>dcrad = dec.to('<STR_LIT>').value<EOL>last = self.compute_lst()<EOL>tellat  = np.deg2rad(self.coords[<NUM_LIT:0>])<EOL>tellong = np.deg2rad(self.coords[<NUM_LIT:1>])<EOL>starvect = s.sla_dcs2c(rarad, dcrad)<EOL>Rgeo = s.sla_rverot( tellat, rarad, dcrad, last)<EOL>evp = s.sla_evp(mjdd, <NUM_LIT>)<EOL>dvb = evp[<NUM_LIT:0>]   <EOL>dpb = evp[<NUM_LIT:1>]   <EOL>dvh = evp[<NUM_LIT:2>]   <EOL>dph = evp[<NUM_LIT:3>]   <EOL>vcorhelio = -s.sla_dvdv( starvect, dvh) *<NUM_LIT><EOL>vcorbary  = -s.sla_dvdv( starvect, dvb) *<NUM_LIT><EOL>rvlsrd = s.sla_rvlsrd( rarad,dcrad)<EOL>rvlsrk = s.sla_rvlsrk( rarad,dcrad)<EOL>rvgalc = s.sla_rvgalc( rarad,dcrad)<EOL>totalhelio = Rgeo + vcorhelio<EOL>totalbary  = Rgeo + vcorbary<EOL>totallsrk = totalhelio + rvlsrk<EOL>totalgal  = totalbary  + rvlsrd + rvgalc<EOL>return totallsrk<EOL>

Computes the LSR in km/s

        uses the MJD, RA and DEC of observation to compute
        along with the telescope location. Requires pyslalib


if n_coarse_chan < <NUM_LIT:1>:<EOL><INDENT>logger.warning('<STR_LIT>')<EOL>return None<EOL><DEDENT>if not n_coarse_chan % int(n_coarse_chan) == <NUM_LIT:0>:<EOL><INDENT>logger.warning('<STR_LIT>')<EOL>return None<EOL><DEDENT>n_coarse_chan = int(n_coarse_chan)<EOL>n_chan = self.data.shape[-<NUM_LIT:1>]<EOL>n_chan_per_coarse = int(n_chan / n_coarse_chan)<EOL>mid_chan = int(n_chan_per_coarse / <NUM_LIT:2>)<EOL>for ii in range(n_coarse_chan):<EOL><INDENT>ss = ii*n_chan_per_coarse<EOL>self.data[..., ss+mid_chan] = np.median(self.data[..., ss+mid_chan+<NUM_LIT:5>:ss+mid_chan+<NUM_LIT:10>])<EOL><DEDENT>

Blank DC bins in coarse channels.

        Note: currently only works if entire file is read


for key, val in self.header.items():<EOL><INDENT>if key == b'<STR_LIT>':<EOL><INDENT>val = val.to_string(unit=u.hour, sep='<STR_LIT::>')<EOL><DEDENT>if key == b'<STR_LIT>':<EOL><INDENT>val = val.to_string(unit=u.deg, sep='<STR_LIT::>')<EOL><DEDENT>if key == b'<STR_LIT>':<EOL><INDENT>val *= u.second<EOL><DEDENT>if key in ('<STR_LIT>', '<STR_LIT>'):<EOL><INDENT>val *= u.MHz<EOL><DEDENT>if key == b'<STR_LIT>':<EOL><INDENT>print("<STR_LIT>" % ("<STR_LIT>", Time(val, format='<STR_LIT>').isot))<EOL>key = "<STR_LIT>"<EOL><DEDENT>print("<STR_LIT>" % (key, val))<EOL><DEDENT>print("<STR_LIT>" % ("<STR_LIT>", self.n_ints_in_file))<EOL>print("<STR_LIT>" % ("<STR_LIT>", self.data.shape))<EOL>print("<STR_LIT>" % ("<STR_LIT>", self.freqs[<NUM_LIT:0>]))<EOL>print("<STR_LIT>" % ("<STR_LIT>", self.freqs[-<NUM_LIT:1>]))<EOL>


def generate_freqs(self, f_start, f_stop):

fch1 = self.header[b'<STR_LIT>']<EOL>foff = self.header[b'<STR_LIT>']<EOL>i_start = int((f_start - fch1) / foff)<EOL>i_stop  = int((f_stop - fch1)  / foff)<EOL>chan_start_idx = np.int(i_start)<EOL>chan_stop_idx  = np.int(i_stop)<EOL>i_vals = np.arange(chan_stop_idx, chan_start_idx, <NUM_LIT:1>)<EOL>freqs = foff * i_vals + fch1<EOL>return freqs<EOL>

returns frequency array [f_start...f_stop]


def grab_data(self, f_start=None, f_stop=None, t_start=None, t_stop=None, if_id=<NUM_LIT:0>):

if f_start is None:<EOL><INDENT>f_start = self.freqs[<NUM_LIT:0>]<EOL><DEDENT>if f_stop is None:<EOL><INDENT>f_stop = self.freqs[-<NUM_LIT:1>]<EOL><DEDENT>i0 = np.argmin(np.abs(self.freqs - f_start))<EOL>i1 = np.argmin(np.abs(self.freqs - f_stop))<EOL>if i0 < i1:<EOL><INDENT>plot_f    = self.freqs[i0:i1 + <NUM_LIT:1>]<EOL>plot_data = np.squeeze(self.data[t_start:t_stop, ..., i0:i1 + <NUM_LIT:1>])<EOL><DEDENT>else:<EOL><INDENT>plot_f    = self.freqs[i1:i0 + <NUM_LIT:1>]<EOL>plot_data = np.squeeze(self.data[t_start:t_stop, ..., i1:i0 + <NUM_LIT:1>])<EOL><DEDENT>return plot_f, plot_data<EOL>

Extract a portion of data by frequency range.

        Args:
            f_start (float): start frequency in MHz
            f_stop (float): stop frequency in MHz
            if_id (int): IF input identification (req. when multiple IFs in file)

        Returns:
            (freqs, data) (np.arrays): frequency axis in MHz and data subset


plot_f_begin = plot_f[<NUM_LIT:0>]<EOL>plot_f_end = plot_f[-<NUM_LIT:1>] + (plot_f[<NUM_LIT:1>]-plot_f[<NUM_LIT:0>])<EOL>plot_t_begin = self.timestamps[<NUM_LIT:0>]<EOL>plot_t_end  = self.timestamps[-<NUM_LIT:1>] + (self.timestamps[<NUM_LIT:1>] - self.timestamps[<NUM_LIT:0>])<EOL>if MJD_time:<EOL><INDENT>extent=(plot_f_begin, plot_f_begin_end, plot_t_begin, plot_t_end)<EOL><DEDENT>else:<EOL><INDENT>extent=(plot_f_begin, plot_f_end, <NUM_LIT:0.0>,(plot_t_end-plot_t_begin)*<NUM_LIT>*<NUM_LIT>*<NUM_LIT>)<EOL><DEDENT>return extent<EOL>


def plot_spectrum(self, t=<NUM_LIT:0>, f_start=None, f_stop=None, logged=False, if_id=<NUM_LIT:0>, c=None, **kwargs):

if self.header[b'<STR_LIT>'] <=<NUM_LIT:2>:<EOL><INDENT>logged = False<EOL>t='<STR_LIT:all>'<EOL><DEDENT>ax = plt.gca()<EOL>plot_f, plot_data = self.grab_data(f_start, f_stop, if_id)<EOL>if self.header[b'<STR_LIT>'] < <NUM_LIT:0>:<EOL><INDENT>plot_data = plot_data[..., ::-<NUM_LIT:1>] <EOL>plot_f = plot_f[::-<NUM_LIT:1>]<EOL><DEDENT>if isinstance(t, int):<EOL><INDENT>print("<STR_LIT>" % t)<EOL>plot_data = plot_data[t]<EOL><DEDENT>elif t == b'<STR_LIT:all>':<EOL><INDENT>print("<STR_LIT>")<EOL>if len(plot_data.shape) > <NUM_LIT:1>:<EOL><INDENT>plot_data = plot_data.mean(axis=<NUM_LIT:0>)<EOL><DEDENT>else:<EOL><INDENT>plot_data = plot_data.mean()<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise RuntimeError("<STR_LIT>" % t)<EOL><DEDENT>dec_fac_x = <NUM_LIT:1><EOL>if plot_data.shape[<NUM_LIT:0>] > MAX_PLT_POINTS:<EOL><INDENT>dec_fac_x = int(plot_data.shape[<NUM_LIT:0>] / MAX_PLT_POINTS)<EOL><DEDENT>plot_data = rebin(plot_data, dec_fac_x, <NUM_LIT:1>)<EOL>plot_f    = rebin(plot_f, dec_fac_x, <NUM_LIT:1>)<EOL>if not c:<EOL><INDENT>kwargs['<STR_LIT:c>'] = '<STR_LIT>'<EOL><DEDENT>if logged:<EOL><INDENT>plt.plot(plot_f, db(plot_data),label='<STR_LIT>', **kwargs)<EOL>plt.ylabel("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>plt.plot(plot_f, plot_data,label='<STR_LIT>', **kwargs)<EOL>plt.ylabel("<STR_LIT>")<EOL><DEDENT>plt.xlabel("<STR_LIT>")<EOL>plt.legend()<EOL>try:<EOL><INDENT>plt.title(self.header[b'<STR_LIT>'])<EOL><DEDENT>except KeyError:<EOL><INDENT>plt.title(self.filename)<EOL><DEDENT>plt.xlim(plot_f[<NUM_LIT:0>], plot_f[-<NUM_LIT:1>])<EOL>

Plot frequency spectrum of a given file

        Args:
            t (int): integration number to plot (0 -> len(data))
            logged (bool): Plot in linear (False) or dB units (True)
            if_id (int): IF identification (if multiple IF signals in file)
            c: color for line
            kwargs: keyword args to be passed to matplotlib plot()


def plot_spectrum_min_max(self, t=<NUM_LIT:0>, f_start=None, f_stop=None, logged=False, if_id=<NUM_LIT:0>, c=None, **kwargs):

ax = plt.gca()<EOL>plot_f, plot_data = self.grab_data(f_start, f_stop, if_id)<EOL>if self.header[b'<STR_LIT>'] < <NUM_LIT:0>:<EOL><INDENT>plot_data = plot_data[..., ::-<NUM_LIT:1>] <EOL>plot_f = plot_f[::-<NUM_LIT:1>]<EOL><DEDENT>fig_max = plot_data[<NUM_LIT:0>].max()<EOL>fig_min = plot_data[<NUM_LIT:0>].min()<EOL>print("<STR_LIT>")<EOL>if len(plot_data.shape) > <NUM_LIT:1>:<EOL><INDENT>plot_max = plot_data.max(axis=<NUM_LIT:0>)<EOL>plot_min = plot_data.min(axis=<NUM_LIT:0>)<EOL>plot_data = plot_data.mean(axis=<NUM_LIT:0>)<EOL><DEDENT>else:<EOL><INDENT>plot_max = plot_data.max()<EOL>plot_min = plot_data.min()<EOL>plot_data = plot_data.mean()<EOL><DEDENT>dec_fac_x = <NUM_LIT:1><EOL>MAX_PLT_POINTS = <NUM_LIT:8>*<NUM_LIT:64>  <EOL>if plot_data.shape[<NUM_LIT:0>] > MAX_PLT_POINTS:<EOL><INDENT>dec_fac_x = int(plot_data.shape[<NUM_LIT:0>] / MAX_PLT_POINTS)<EOL><DEDENT>plot_data = rebin(plot_data, dec_fac_x, <NUM_LIT:1>)<EOL>plot_min = rebin(plot_min, dec_fac_x, <NUM_LIT:1>)<EOL>plot_max = rebin(plot_max, dec_fac_x, <NUM_LIT:1>)<EOL>plot_f    = rebin(plot_f, dec_fac_x, <NUM_LIT:1>)<EOL>if logged:<EOL><INDENT>plt.plot(plot_f, db(plot_data), "<STR_LIT>", label='<STR_LIT>', **kwargs)<EOL>plt.plot(plot_f, db(plot_max),  "<STR_LIT>", label='<STR_LIT>', **kwargs)<EOL>plt.plot(plot_f, db(plot_min),  '<STR_LIT>', label='<STR_LIT>', **kwargs)<EOL>plt.ylabel("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>plt.plot(plot_f, plot_data,  "<STR_LIT>", label='<STR_LIT>', **kwargs)<EOL>plt.plot(plot_f, plot_max,   "<STR_LIT>", label='<STR_LIT>', **kwargs)<EOL>plt.plot(plot_f, plot_min,   '<STR_LIT>', label='<STR_LIT>', **kwargs)<EOL>plt.ylabel("<STR_LIT>")<EOL><DEDENT>plt.xlabel("<STR_LIT>")<EOL>plt.legend()<EOL>try:<EOL><INDENT>plt.title(self.header[b'<STR_LIT>'])<EOL><DEDENT>except KeyError:<EOL><INDENT>plt.title(self.filename)<EOL><DEDENT>plt.xlim(plot_f[<NUM_LIT:0>], plot_f[-<NUM_LIT:1>])<EOL>if logged:<EOL><INDENT>plt.ylim(db(fig_min),db(fig_max))<EOL><DEDENT>

Plot frequency spectrum of a given file

        Args:
            logged (bool): Plot in linear (False) or dB units (True)
            if_id (int): IF identification (if multiple IF signals in file)
            c: color for line
            kwargs: keyword args to be passed to matplotlib plot()


def plot_waterfall(self, f_start=None, f_stop=None, if_id=<NUM_LIT:0>, logged=True, cb=True, MJD_time=False, **kwargs):

plot_f, plot_data = self.grab_data(f_start, f_stop, if_id)<EOL>if self.header[b'<STR_LIT>'] < <NUM_LIT:0>:<EOL><INDENT>plot_data = plot_data[..., ::-<NUM_LIT:1>] <EOL>plot_f = plot_f[::-<NUM_LIT:1>]<EOL><DEDENT>if logged:<EOL><INDENT>plot_data = db(plot_data)<EOL><DEDENT>dec_fac_x, dec_fac_y = <NUM_LIT:1>, <NUM_LIT:1><EOL>if plot_data.shape[<NUM_LIT:0>] > MAX_IMSHOW_POINTS[<NUM_LIT:0>]:<EOL><INDENT>dec_fac_x = int(plot_data.shape[<NUM_LIT:0>] / MAX_IMSHOW_POINTS[<NUM_LIT:0>])<EOL><DEDENT>if plot_data.shape[<NUM_LIT:1>] > MAX_IMSHOW_POINTS[<NUM_LIT:1>]:<EOL><INDENT>dec_fac_y =  int(plot_data.shape[<NUM_LIT:1>] /  MAX_IMSHOW_POINTS[<NUM_LIT:1>])<EOL><DEDENT>plot_data = rebin(plot_data, dec_fac_x, dec_fac_y)<EOL>try:<EOL><INDENT>plt.title(self.header[b'<STR_LIT>'])<EOL><DEDENT>except KeyError:<EOL><INDENT>plt.title(self.filename)<EOL><DEDENT>extent = self._calc_extent(plot_f=plot_f,plot_t=self.timestamps,MJD_time=MJD_time)<EOL>plt.imshow(plot_data,<EOL>aspect='<STR_LIT>',<EOL>origin='<STR_LIT>',<EOL>rasterized=True,<EOL>interpolation='<STR_LIT>',<EOL>extent=extent,<EOL>cmap='<STR_LIT>',<EOL>**kwargs<EOL>)<EOL>if cb:<EOL><INDENT>plt.colorbar()<EOL><DEDENT>plt.xlabel("<STR_LIT>")<EOL>if MJD_time:<EOL><INDENT>plt.ylabel("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel("<STR_LIT>")<EOL><DEDENT>

Plot waterfall of data

        Args:
            f_start (float): start frequency, in MHz
            f_stop (float): stop frequency, in MHz
            logged (bool): Plot in linear (False) or dB units (True),
            cb (bool): for plotting the colorbar
            kwargs: keyword args to be passed to matplotlib imshow()


def plot_time_series(self, f_start=None, f_stop=None, if_id=<NUM_LIT:0>, logged=True, orientation='<STR_LIT:h>', MJD_time=False, **kwargs):

ax = plt.gca()<EOL>plot_f, plot_data = self.grab_data(f_start, f_stop, if_id)<EOL>if logged and self.header[b'<STR_LIT>'] >= <NUM_LIT:8>:<EOL><INDENT>plot_data = db(plot_data)<EOL><DEDENT>if len(plot_data.shape) > <NUM_LIT:1>:<EOL><INDENT>plot_data = plot_data.mean(axis=<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>plot_data = plot_data.mean()<EOL><DEDENT>extent = self._calc_extent(plot_f=plot_f,plot_t=self.timestamps,MJD_time=MJD_time)<EOL>plot_t = np.linspace(extent[<NUM_LIT:2>],extent[<NUM_LIT:3>],len(self.timestamps))<EOL>if MJD_time:<EOL><INDENT>tlabel = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>tlabel = "<STR_LIT>"<EOL><DEDENT>if logged:<EOL><INDENT>plabel = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>plabel = "<STR_LIT>"<EOL><DEDENT>if '<STR_LIT:v>' in orientation:<EOL><INDENT>plt.plot(plot_data, plot_t, **kwargs)<EOL>plt.xlabel(plabel)<EOL><DEDENT>else:<EOL><INDENT>plt.plot(plot_t, plot_data, **kwargs)<EOL>plt.xlabel(tlabel)<EOL>plt.ylabel(plabel)<EOL><DEDENT>ax.autoscale(axis='<STR_LIT>',tight=True)<EOL>

Plot the time series.

         Args:
            f_start (float): start frequency, in MHz
            f_stop (float): stop frequency, in MHz
            logged (bool): Plot in linear (False) or dB units (True),
            kwargs: keyword args to be passed to matplotlib imshow()


def plot_kurtosis(self, f_start=None, f_stop=None, if_id=<NUM_LIT:0>, **kwargs):

ax = plt.gca()<EOL>plot_f, plot_data = self.grab_data(f_start, f_stop, if_id)<EOL>if self.header[b'<STR_LIT>'] < <NUM_LIT:0>:<EOL><INDENT>plot_data = plot_data[..., ::-<NUM_LIT:1>] <EOL>plot_f = plot_f[::-<NUM_LIT:1>]<EOL><DEDENT>try:<EOL><INDENT>plot_kurtosis = scipy.stats.kurtosis(plot_data, axis=<NUM_LIT:0>, nan_policy='<STR_LIT>')<EOL><DEDENT>except:<EOL><INDENT>plot_kurtosis = plot_data*<NUM_LIT:0.0><EOL><DEDENT>plt.plot(plot_f, plot_kurtosis, **kwargs)<EOL>plt.ylabel("<STR_LIT>")<EOL>plt.xlabel("<STR_LIT>")<EOL>plt.xlim(plot_f[<NUM_LIT:0>], plot_f[-<NUM_LIT:1>])<EOL>

Plot kurtosis

         Args:
            f_start (float): start frequency, in MHz
            f_stop (float): stop frequency, in MHz
            kwargs: keyword args to be passed to matplotlib imshow()


def plot_all(self, t=<NUM_LIT:0>, f_start=None, f_stop=None, logged=False, if_id=<NUM_LIT:0>, kurtosis=True, **kwargs):

if self.header[b'<STR_LIT>'] <=<NUM_LIT:2>:<EOL><INDENT>logged = False<EOL><DEDENT>nullfmt = NullFormatter()  <EOL>left, width = <NUM_LIT>, <NUM_LIT:0.5><EOL>bottom, height = <NUM_LIT>, <NUM_LIT:0.5><EOL>width2, height2 = <NUM_LIT>, <NUM_LIT><EOL>bottom2, left2 = bottom - height2 - <NUM_LIT>, left - width2 - <NUM_LIT><EOL>bottom3, left3 = bottom2 - height2 - <NUM_LIT>, <NUM_LIT><EOL>rect_waterfall = [left, bottom, width, height]<EOL>rect_colorbar = [left + width, bottom, <NUM_LIT>, height]<EOL>rect_spectrum = [left, bottom2, width, height2]<EOL>rect_min_max = [left, bottom3, width, height2]<EOL>rect_timeseries = [left + width, bottom, width2, height]<EOL>rect_kurtosis = [left3, bottom3, <NUM_LIT>, height2]<EOL>rect_header = [left3 - <NUM_LIT>, bottom, <NUM_LIT>, height]<EOL>axMinMax = plt.axes(rect_min_max)<EOL>print('<STR_LIT>')<EOL>self.plot_spectrum_min_max(logged=logged, f_start=f_start, f_stop=f_stop, t=t)<EOL>plt.title('<STR_LIT>')<EOL>axMinMax.yaxis.tick_right()<EOL>axMinMax.yaxis.set_label_position("<STR_LIT:right>")<EOL>axSpectrum = plt.axes(rect_spectrum,sharex=axMinMax)<EOL>print('<STR_LIT>')<EOL>self.plot_spectrum(logged=logged, f_start=f_start, f_stop=f_stop, t=t)<EOL>plt.title('<STR_LIT>')<EOL>axSpectrum.yaxis.tick_right()<EOL>axSpectrum.yaxis.set_label_position("<STR_LIT:right>")<EOL>plt.xlabel('<STR_LIT>')<EOL><INDENT>axSpectrum.xaxis.set_major_formatter(nullfmt)<EOL><DEDENT>plt.setp(axSpectrum.get_xticklabels(), visible=False)<EOL>axWaterfall = plt.axes(rect_waterfall,sharex=axMinMax)<EOL>print('<STR_LIT>')<EOL>self.plot_waterfall(f_start=f_start, f_stop=f_stop, logged=logged, cb=False)<EOL>plt.xlabel('<STR_LIT>')<EOL><INDENT>axWaterfall.xaxis.set_major_formatter(nullfmt)<EOL><DEDENT>plt.setp(axWaterfall.get_xticklabels(), visible=False)<EOL>axTimeseries = plt.axes(rect_timeseries)<EOL>print('<STR_LIT>')<EOL>self.plot_time_series(f_start=f_start, f_stop=f_stop, orientation='<STR_LIT:v>')<EOL>axTimeseries.yaxis.set_major_formatter(nullfmt)<EOL><INDENT>axTimeseries.xaxis.set_major_formatter(nullfmt)<EOL><DEDENT>if kurtosis:<EOL><INDENT>axKurtosis = plt.axes(rect_kurtosis)<EOL>print('<STR_LIT>')<EOL>self.plot_kurtosis(f_start=f_start, f_stop=f_stop)<EOL><DEDENT>axHeader = plt.axes(rect_header)<EOL>print('<STR_LIT>')<EOL>telescopes = {<NUM_LIT:0>: '<STR_LIT>',<EOL><NUM_LIT:1>: '<STR_LIT>',<EOL><NUM_LIT:2>: '<STR_LIT>',<EOL><NUM_LIT:3>: '<STR_LIT>',<EOL><NUM_LIT:4>: '<STR_LIT>',<EOL><NUM_LIT:5>: '<STR_LIT>',<EOL><NUM_LIT:6>: '<STR_LIT>',<EOL><NUM_LIT:8>: '<STR_LIT>',<EOL><NUM_LIT:10>: '<STR_LIT>',<EOL><NUM_LIT:64>: '<STR_LIT>',<EOL><NUM_LIT>: '<STR_LIT>'<EOL>}<EOL>telescope = telescopes.get(self.header[b"<STR_LIT>"], self.header[b"<STR_LIT>"])<EOL>plot_header = "<STR_LIT>" % ("<STR_LIT>", telescope)<EOL>for key in (b'<STR_LIT>', b'<STR_LIT>', b'<STR_LIT>', b'<STR_LIT>', b'<STR_LIT>', b'<STR_LIT>', b'<STR_LIT>'):<EOL><INDENT>try:<EOL><INDENT>plot_header += "<STR_LIT>" % (key, self.header[key.lower()])<EOL><DEDENT>except KeyError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>fch1 = "<STR_LIT>" % self.header[b'<STR_LIT>']<EOL>foff = (self.header[b'<STR_LIT>'] * <NUM_LIT> * u.Hz)<EOL>if np.abs(foff) > <NUM_LIT> * u.Hz:<EOL><INDENT>foff = str(foff.to('<STR_LIT>'))<EOL><DEDENT>elif np.abs(foff) > <NUM_LIT> * u.Hz:<EOL><INDENT>foff = str(foff.to('<STR_LIT>'))<EOL><DEDENT>else:<EOL><INDENT>foff = str(foff.to('<STR_LIT>'))<EOL><DEDENT>plot_header += "<STR_LIT>" % ("<STR_LIT>", fch1)<EOL>plot_header += "<STR_LIT>" % ("<STR_LIT>", foff)<EOL>plt.text(<NUM_LIT>, <NUM_LIT>, plot_header, ha='<STR_LIT:left>', va='<STR_LIT>', wrap=True)<EOL>axHeader.set_facecolor('<STR_LIT>')<EOL>axHeader.xaxis.set_major_formatter(nullfmt)<EOL>axHeader.yaxis.set_major_formatter(nullfmt)<EOL>

Plot waterfall of data as well as spectrum; also, placeholder to make even more complicated plots in the future.

        Args:
            f_start (float): start frequency, in MHz
            f_stop (float): stop frequency, in MHz
            logged (bool): Plot in linear (False) or dB units (True),
            t (int): integration number to plot (0 -> len(data))
            logged (bool): Plot in linear (False) or dB units (True)
            if_id (int): IF identification (if multiple IF signals in file)
            kwargs: keyword args to be passed to matplotlib plot() and imshow()


print("<STR_LIT>")<EOL>n_bytes  = int(self.header[b'<STR_LIT>'] / <NUM_LIT:8>)<EOL>with open(filename_out, "<STR_LIT:wb>") as fileh:<EOL><INDENT>fileh.write(generate_sigproc_header(self))<EOL>j = self.data<EOL>if n_bytes == <NUM_LIT:4>:<EOL><INDENT>np.float32(j.ravel()).tofile(fileh)<EOL><DEDENT>elif n_bytes == <NUM_LIT:2>:<EOL><INDENT>np.int16(j.ravel()).tofile(fileh)<EOL><DEDENT>elif n_bytes == <NUM_LIT:1>:<EOL><INDENT>np.int8(j.ravel()).tofile(fileh)<EOL><DEDENT><DEDENT>

Write data to blimpy file.

        Args:
            filename_out (str): Name of output file


def write_to_hdf5(self, filename_out, *args, **kwargs):

print("<STR_LIT>")<EOL>if not HAS_HDF5:<EOL><INDENT>raise RuntimeError("<STR_LIT>")<EOL><DEDENT>with h5py.File(filename_out, '<STR_LIT:w>') as h5:<EOL><INDENT>dset = h5.create_dataset(b'<STR_LIT:data>',<EOL>data=self.data,<EOL>compression='<STR_LIT>')<EOL>dset_mask = h5.create_dataset(b'<STR_LIT>',<EOL>shape=self.data.shape,<EOL>compression='<STR_LIT>',<EOL>dtype='<STR_LIT>')<EOL>dset.dims[<NUM_LIT:0>].label = b"<STR_LIT>"<EOL>dset.dims[<NUM_LIT:1>].label = b"<STR_LIT>"<EOL>dset.dims[<NUM_LIT:2>].label = b"<STR_LIT:time>"<EOL>dset_mask.dims[<NUM_LIT:0>].label = b"<STR_LIT>"<EOL>dset_mask.dims[<NUM_LIT:1>].label = b"<STR_LIT>"<EOL>dset_mask.dims[<NUM_LIT:2>].label = b"<STR_LIT:time>"<EOL>for key, value in self.header.items():<EOL><INDENT>dset.attrs[key] = value<EOL><DEDENT><DEDENT>

Write data to HDF5 file.

        Args:
            filename_out (str): Name of output file


band_pass = np.median(self.data.squeeze(),axis=<NUM_LIT:0>)<EOL>self.data = self.data/band_pass<EOL>

One way to calibrate the band pass is to take the median value
            for every frequency fine channel, and divide by it.


self.yr = int(year)<EOL>

Initializes a Season object for an NBA season.

        :year: The year of the season we want.


url = (sportsref.nba.BASE_URL +<EOL>'<STR_LIT>'.format(self.yr))<EOL>return pq(sportsref.utils.get_html(url))<EOL>

Returns PyQuery object for the main season URL.
        :returns: PyQuery object.


html = sportsref.utils.get_html(self._subpage_url(subpage))<EOL>return pq(html)<EOL>

Returns PyQuery object for a given subpage URL.
        :subpage: The subpage of the season, e.g. 'per_game'.
        :returns: PyQuery object.


df = self.team_stats_per_game()<EOL>if not df.empty:<EOL><INDENT>return df.index.tolist()<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL>return []<EOL><DEDENT>

Returns a list of the team IDs for the given year.
        :returns: List of team IDs.


doc = self.get_main_doc()<EOL>table = doc('<STR_LIT>')<EOL>flattened = sportsref.utils.parse_table(table, flatten=True)<EOL>unflattened = sportsref.utils.parse_table(table, flatten=False)<EOL>team_ids = flattened['<STR_LIT>']<EOL>team_names = unflattened['<STR_LIT>']<EOL>if len(team_names) != len(team_ids):<EOL><INDENT>raise Exception("<STR_LIT>")<EOL><DEDENT>return dict(zip(team_ids, team_names))<EOL>

Mapping from 3-letter team IDs to full team names.
        :returns: Dictionary with team IDs as keys and full team strings as
        values.


d = self.team_ids_to_names()<EOL>return {v: k for k, v in d.items()}<EOL>

Mapping from full team names to 3-letter team IDs.
        :returns: Dictionary with tean names as keys and team IDs as values.


kind = kind.upper()[<NUM_LIT:0>]<EOL>dfs = []<EOL>for month in ('<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>',<EOL>'<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>'):<EOL><INDENT>try:<EOL><INDENT>doc = self.get_sub_doc('<STR_LIT>'.format(month))<EOL><DEDENT>except ValueError:<EOL><INDENT>continue<EOL><DEDENT>table = doc('<STR_LIT>')<EOL>df = sportsref.utils.parse_table(table)<EOL>dfs.append(df)<EOL><DEDENT>df = pd.concat(dfs).reset_index(drop=True)<EOL>try:<EOL><INDENT>sportsref.utils.get_html('<STR_LIT>'.format(<EOL>sportsref.nba.BASE_URL, self.yr)<EOL>)<EOL>is_past_season = True<EOL><DEDENT>except ValueError:<EOL><INDENT>is_past_season = False<EOL><DEDENT>if is_past_season:<EOL><INDENT>team_per_game = self.team_stats_per_game()<EOL>n_reg_games = int(team_per_game.g.sum() // <NUM_LIT:2>)<EOL><DEDENT>else:<EOL><INDENT>n_reg_games = len(df)<EOL><DEDENT>if kind == '<STR_LIT:P>':<EOL><INDENT>return df.iloc[n_reg_games:]<EOL><DEDENT>else:<EOL><INDENT>return df.iloc[:n_reg_games]<EOL><DEDENT>

Returns a list of BoxScore IDs for every game in the season.
        Only needs to handle 'R' or 'P' options because decorator handles 'B'.

        :param kind: 'R' for regular season, 'P' for playoffs, 'B' for both.
            Defaults to 'R'.
        :returns: DataFrame of schedule information.
        :rtype: pd.DataFrame


raise NotImplementedError('<STR_LIT>')<EOL>

Returns the team ID for the winner of that year's NBA Finals.
        :returns: 3-letter team ID for champ.


Returns the team ID for the loser of that year's NBA Finals.
        :returns: 3-letter team ID for runner-up.


doc = self.get_sub_doc('<STR_LIT>')<EOL>east_table = doc('<STR_LIT>')<EOL>east_df = pd.DataFrame(sportsref.utils.parse_table(east_table))<EOL>east_df.sort_values('<STR_LIT>', ascending=False, inplace=True)<EOL>east_df['<STR_LIT>'] = range(<NUM_LIT:1>, len(east_df) + <NUM_LIT:1>)<EOL>east_df['<STR_LIT>'] = '<STR_LIT:E>'<EOL>west_table = doc('<STR_LIT>')<EOL>west_df = sportsref.utils.parse_table(west_table)<EOL>west_df.sort_values('<STR_LIT>', ascending=False, inplace=True)<EOL>west_df['<STR_LIT>'] = range(<NUM_LIT:1>, len(west_df) + <NUM_LIT:1>)<EOL>west_df['<STR_LIT>'] = '<STR_LIT>'<EOL>full_df = pd.concat([east_df, west_df], axis=<NUM_LIT:0>).reset_index(drop=True)<EOL>full_df['<STR_LIT>'] = full_df.team_id.str.extract(r'<STR_LIT>', expand=False)<EOL>full_df['<STR_LIT>'] = [gb if isinstance(gb, int) or isinstance(gb, float) else <NUM_LIT:0><EOL>for gb in full_df['<STR_LIT>']]<EOL>full_df = full_df.drop('<STR_LIT>', axis=<NUM_LIT:1>)<EOL>expanded_table = doc('<STR_LIT>')<EOL>expanded_df = sportsref.utils.parse_table(expanded_table)<EOL>full_df = pd.merge(full_df, expanded_df, on='<STR_LIT>')<EOL>return full_df<EOL>

Returns a DataFrame containing standings information.


doc = self.get_main_doc()<EOL>table = doc(selector)<EOL>df = sportsref.utils.parse_table(table)<EOL>df.set_index('<STR_LIT>', inplace=True)<EOL>return df<EOL>

Helper function for stats tables on season pages. Returns a
        DataFrame.


return self._get_team_stats_table('<STR_LIT>')<EOL>

Returns a Pandas DataFrame of each team's basic per-game stats for
        the season.


Returns a Pandas DataFrame of each team's opponent's basic per-game
        stats for the season.


Returns a Pandas DataFrame of each team's basic stat totals for the
        season.


Returns a Pandas DataFrame of each team's opponent's basic stat
        totals for the season.


Returns a Pandas DataFrame of miscellaneous stats about each team's
        season.


Returns a Pandas DataFrame of each team's shooting stats for the
        season.


Returns a Pandas DataFrame of each team's opponent's shooting stats
        for the season.


doc = self.get_sub_doc(identifier)<EOL>table = doc('<STR_LIT>'.format(identifier))<EOL>df = sportsref.utils.parse_table(table)<EOL>return df<EOL>

Helper function for player season stats.

        :identifier: string identifying the type of stat, e.g. 'per_game'.
        :returns: A DataFrame of stats.


return self._get_player_stats_table('<STR_LIT>')<EOL>

Returns a DataFrame of per-game player stats for a season.


Returns a DataFrame of player stat totals for a season.


Returns a DataFrame of player per-36 min stats for a season.


Returns a DataFrame of player per-100 poss stats for a season.


Returns a DataFrame containing information about MVP voting.


url = '<STR_LIT>'.format(sportsref.nba.BASE_URL, self.yr)<EOL>doc = pq(sportsref.utils.get_html(url))<EOL>table = doc('<STR_LIT>')<EOL>df = sportsref.utils.parse_table(table)<EOL>return df<EOL>

Returns a DataFrame containing information about ROY voting.


doc = self.get_main_doc()<EOL>return doc('<STR_LIT>').text()<EOL>

Returns the name of the player as a string.


@sportsref.decorators.memoize<EOL><INDENT>def age(self, year, month=<NUM_LIT:2>, day=<NUM_LIT:1>):<DEDENT>

doc = self.get_main_doc()<EOL>date_string = doc('<STR_LIT>').attr('<STR_LIT>')<EOL>regex = r'<STR_LIT>'<EOL>date_args = map(int, re.match(regex, date_string).groups())<EOL>birth_date = datetime.date(*date_args)<EOL>age_date = datetime.date(year=year, month=month, day=day)<EOL>delta = age_date - birth_date<EOL>age = delta.days / <NUM_LIT><EOL>return age<EOL>

Returns the age of the player on a given date.

        :year: int representing the year.
        :month: int representing the month (1-12).
        :day: int representing the day within the month (1-31).
        :returns: Age in years as a float.


raise Exception('<STR_LIT>')<EOL>

TODO: Docstring for position.
        :returns: TODO


doc = self.get_main_doc()<EOL>raw = doc('<STR_LIT>').text()<EOL>try:<EOL><INDENT>feet, inches = map(int, raw.split('<STR_LIT:->'))<EOL>return feet * <NUM_LIT:12> + inches<EOL><DEDENT>except ValueError:<EOL><INDENT>return None<EOL><DEDENT>

Returns the player's height (in inches).
        :returns: An int representing a player's height in inches.


doc = self.get_main_doc()<EOL>raw = doc('<STR_LIT>').text()<EOL>try:<EOL><INDENT>weight = re.match(r'<STR_LIT>', raw).group(<NUM_LIT:1>)<EOL>return int(weight)<EOL><DEDENT>except ValueError:<EOL><INDENT>return None<EOL><DEDENT>

Returns the player's weight (in pounds).
        :returns: An int representing a player's weight in pounds.


doc = self.get_main_doc()<EOL>hand = re.search(r'<STR_LIT>', doc.text()).group(<NUM_LIT:1>)<EOL>return hand<EOL>

Returns the player's handedness.
        :returns: 'L' for left-handed, 'R' for right-handed.


doc = self.get_main_doc()<EOL>try:<EOL><INDENT>p_tags = doc('<STR_LIT>')<EOL>draft_p_tag = next(p for p in p_tags.items() if p.text().lower().startswith('<STR_LIT>'))<EOL>draft_pick = int(re.search(r'<STR_LIT>', draft_p_tag.text()).group(<NUM_LIT:1>))<EOL>return draft_pick<EOL><DEDENT>except Exception as e:<EOL><INDENT>return None<EOL><DEDENT>

Returns when in the draft the player was picked.
        :returns: TODO


raise Exception('<STR_LIT>')<EOL>

Returns the year the player was selected (or undrafted).
        :returns: TODO


@sportsref.decorators.kind_rpb(include_type=True)<EOL><INDENT>def _get_stats_table(self, table_id, kind='<STR_LIT:R>', summary=False):<DEDENT>

doc = self.get_main_doc()<EOL>table_id = '<STR_LIT>'.format(<EOL>'<STR_LIT>' if kind == '<STR_LIT:P>' else '<STR_LIT>', table_id)<EOL>table = doc(table_id)<EOL>df = sportsref.utils.parse_table(table, flatten=(not summary),<EOL>footer=summary)<EOL>return df<EOL>

Gets a stats table from the player page; helper function that does
        the work for per-game, per-100-poss, etc. stats.

        :table_id: the ID of the HTML table.
        :kind: specifies regular season, playoffs, or both. One of 'R', 'P',
            'B'. Defaults to 'R'.
        :returns: A DataFrame of stats.


@sportsref.decorators.memoize<EOL><INDENT>def stats_per_game(self, kind='<STR_LIT:R>', summary=False):<DEDENT>

return self._get_stats_table('<STR_LIT>', kind=kind, summary=summary)<EOL>

Returns a DataFrame of per-game box score stats.


@sportsref.decorators.memoize<EOL><INDENT>def stats_totals(self, kind='<STR_LIT:R>', summary=False):<DEDENT>

Returns a DataFrame of total box score statistics by season.


@sportsref.decorators.memoize<EOL><INDENT>def stats_per36(self, kind='<STR_LIT:R>', summary=False):<DEDENT>

Returns a DataFrame of per-36-minutes stats.


@sportsref.decorators.memoize<EOL><INDENT>def stats_per100(self, kind='<STR_LIT:R>', summary=False):<DEDENT>

Returns a DataFrame of per-100-possession stats.


@sportsref.decorators.memoize<EOL><INDENT>def stats_advanced(self, kind='<STR_LIT:R>', summary=False):<DEDENT>


@sportsref.decorators.memoize<EOL><INDENT>def stats_shooting(self, kind='<STR_LIT:R>', summary=False):<DEDENT>


@sportsref.decorators.memoize<EOL><INDENT>def stats_pbp(self, kind='<STR_LIT:R>', summary=False):<DEDENT>

return self._get_stats_table('<STR_LIT>', kind=kind,<EOL>summary=summary)<EOL>

Returns a DataFrame of play-by-play stats.


doc = self.get_sub_doc('<STR_LIT>'.format(year))<EOL>table = (doc('<STR_LIT>')<EOL>if kind == '<STR_LIT:P>' else doc('<STR_LIT>'))<EOL>df = sportsref.utils.parse_table(table)<EOL>return df<EOL>

Returns a table of a player's basic game-by-game stats for a season.

        :param year: The year representing the desired season.
        :param kind: specifies regular season, playoffs, or both. One of 'R',
            'P', 'B'. Defaults to 'R'.
        :returns: A DataFrame of the player's standard boxscore stats from each
            game of the season.
        :rtype: pd.DataFrame


Returns a table of a player's advanced game-by-game stats for a
        season.

        :param year: The year representing the desired season.
        :param kind: specifies regular season, playoffs, or both. One of 'R',
            'P', 'B'. Defaults to 'R'.
        :returns: A DataFrame of the player's advanced stats from each game of
            the season.
        :rtype: pd.DataFrame


match = re.match(r'<STR_LIT>', self.boxscore_id)<EOL>year, month, day = map(int, match.groups())<EOL>return datetime.date(year=year, month=month, day=day)<EOL>

Returns the date of the game. See Python datetime.date documentation
        for more.
        :returns: A datetime.date object with year, month, and day attributes.


doc = self.get_main_doc()<EOL>table = doc('<STR_LIT>')<EOL>columns = [th.text() for th in table('<STR_LIT>').items('<STR_LIT>')]<EOL>columns[<NUM_LIT:0>] = '<STR_LIT>'<EOL>data = [<EOL>[sportsref.utils.flatten_links(td) for td in tr('<STR_LIT>').items()]<EOL>for tr in table('<STR_LIT>').next_all('<STR_LIT>').items()<EOL>]<EOL>return pd.DataFrame(data, index=['<STR_LIT>', '<STR_LIT>'],<EOL>columns=columns, dtype='<STR_LIT:float>')<EOL>

Returns the linescore for the game as a DataFrame.


linescore = self.linescore()<EOL>return linescore.loc['<STR_LIT>', '<STR_LIT>']<EOL>

Returns home team ID.
        :returns: 3-character string representing home team's ID.


Returns away team ID.
        :returns: 3-character string representing away team's ID.


linescore = self.linescore()<EOL>return linescore.loc['<STR_LIT>', '<STR_LIT:T>']<EOL>

Returns score of the home team.
        :returns: int of the home score.


Returns score of the away team.
        :returns: int of the away score.


hmScore = self.home_score()<EOL>awScore = self.away_score()<EOL>if hmScore > awScore:<EOL><INDENT>return self.home()<EOL><DEDENT>elif hmScore < awScore:<EOL><INDENT>return self.away()<EOL><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT>

Returns the team ID of the winning team. Returns NaN if a tie.


d = self.date()<EOL>if d.month >= <NUM_LIT:9>:<EOL><INDENT>return d.year + <NUM_LIT:1><EOL><DEDENT>else:<EOL><INDENT>return d.year<EOL><DEDENT>

Returns the year ID of the season in which this game took place.

:returns: An int representing the year of the season.


<EOL>doc = self.get_main_doc()<EOL>tms = self.away(), self.home()<EOL>tm_ids = [table_id_fmt.format(tm) for tm in tms]<EOL>tables = [doc('<STR_LIT>'.format(tm_id).lower()) for tm_id in tm_ids]<EOL>dfs = [sportsref.utils.parse_table(table) for table in tables]<EOL>for i, (tm, df) in enumerate(zip(tms, dfs)):<EOL><INDENT>no_time = df['<STR_LIT>'] == <NUM_LIT:0><EOL>stat_cols = [col for col, dtype in df.dtypes.items()<EOL>if dtype != '<STR_LIT:object>']<EOL>df.loc[no_time, stat_cols] = <NUM_LIT:0><EOL>df['<STR_LIT>'] = tm<EOL>df['<STR_LIT>'] = i == <NUM_LIT:1><EOL>df['<STR_LIT>'] = [p < <NUM_LIT:5> for p in range(df.shape[<NUM_LIT:0>])]<EOL>df.drop_duplicates(subset='<STR_LIT>', keep='<STR_LIT>', inplace=True)<EOL><DEDENT>return pd.concat(dfs)<EOL>

Returns a DataFrame of player stats from the game (either basic or
        advanced, depending on the argument.

        :param table_id_fmt: Format string for str.format with a placeholder
            for the team ID (e.g. 'box_{}_basic')
        :returns: DataFrame of player stats


return self._get_player_stats('<STR_LIT>')<EOL>

Returns a DataFrame of basic player stats from the game.


Returns a DataFrame of advanced player stats from the game.


@sportsref.decorators.memoize<EOL><INDENT>def pbp(self, dense_lineups=False, sparse_lineups=False):<DEDENT>

try:<EOL><INDENT>doc = self.get_subpage_doc('<STR_LIT>')<EOL><DEDENT>except:<EOL><INDENT>raise ValueError(<EOL>'<STR_LIT>'<EOL>.format(self.boxscore_id)<EOL>)<EOL><DEDENT>table = doc('<STR_LIT>')<EOL>trs = [<EOL>tr for tr in table('<STR_LIT>').items()<EOL>if (not tr.attr['<STR_LIT:class>'] or  <EOL>tr.attr['<STR_LIT:id>'] and tr.attr['<STR_LIT:id>'].startswith('<STR_LIT:q>'))  <EOL>]<EOL>rows = [tr.children('<STR_LIT>') for tr in trs]<EOL>n_rows = len(trs)<EOL>data = []<EOL>cur_qtr = <NUM_LIT:0><EOL>bsid = self.boxscore_id<EOL>for i in range(n_rows):<EOL><INDENT>tr = trs[i]<EOL>row = rows[i]<EOL>p = {}<EOL>if tr.attr['<STR_LIT:id>'] and tr.attr['<STR_LIT:id>'].startswith('<STR_LIT:q>'):<EOL><INDENT>assert int(tr.attr['<STR_LIT:id>'][<NUM_LIT:1>:]) == cur_qtr + <NUM_LIT:1><EOL>cur_qtr += <NUM_LIT:1><EOL>continue<EOL><DEDENT>t_str = row.eq(<NUM_LIT:0>).text()<EOL>t_regex = r'<STR_LIT>'<EOL>mins, secs, tenths = map(int, re.match(t_regex, t_str).groups())<EOL>endQ = (<NUM_LIT:12> * <NUM_LIT> * min(cur_qtr, <NUM_LIT:4>) +<EOL><NUM_LIT:5> * <NUM_LIT> * (cur_qtr - <NUM_LIT:4> if cur_qtr > <NUM_LIT:4> else <NUM_LIT:0>))<EOL>secsElapsed = endQ - (<NUM_LIT> * mins + secs + <NUM_LIT:0.1> * tenths)<EOL>p['<STR_LIT>'] = secsElapsed<EOL>p['<STR_LIT>'] = t_str<EOL>p['<STR_LIT>'] = cur_qtr<EOL>if row.length == <NUM_LIT:2>:<EOL><INDENT>desc = row.eq(<NUM_LIT:1>)<EOL>if desc.text().lower().startswith('<STR_LIT>'):<EOL><INDENT>p['<STR_LIT>'] = True<EOL>jb_str = sportsref.utils.flatten_links(desc)<EOL>p.update(<EOL>sportsref.nba.pbp.parse_play(bsid, jb_str, None)<EOL>)<EOL><DEDENT>elif (<EOL>desc.text().lower().startswith('<STR_LIT>') or<EOL>desc.text().lower().startswith('<STR_LIT>')<EOL>):<EOL><INDENT>continue<EOL><DEDENT>else:<EOL><INDENT>if not desc.text().lower().startswith('<STR_LIT>'):<EOL><INDENT>print(<EOL>'<STR_LIT>'<EOL>.format(self.boxscore_id, cur_qtr,<EOL>t_str, desc.text())<EOL>)<EOL><DEDENT>continue<EOL><DEDENT><DEDENT>elif row.length == <NUM_LIT:6>:<EOL><INDENT>aw_desc, hm_desc = row.eq(<NUM_LIT:1>), row.eq(<NUM_LIT:5>)<EOL>is_hm_play = bool(hm_desc.text())<EOL>desc = hm_desc if is_hm_play else aw_desc<EOL>desc = sportsref.utils.flatten_links(desc)<EOL>new_p = sportsref.nba.pbp.parse_play(bsid, desc, is_hm_play)<EOL>if not new_p:<EOL><INDENT>continue<EOL><DEDENT>elif isinstance(new_p, list):<EOL><INDENT>orig_p = dict(p)<EOL>p.update(new_p[<NUM_LIT:0>])<EOL>data.append(p)<EOL>p = orig_p<EOL>new_p = new_p[<NUM_LIT:1>]<EOL><DEDENT>elif new_p.get('<STR_LIT>'):<EOL><INDENT>print("<STR_LIT>"<EOL>.format(desc, self.boxscore_id))<EOL><DEDENT>p.update(new_p)<EOL><DEDENT>else:<EOL><INDENT>raise Exception(("<STR_LIT>"<EOL>.format(row.length)))<EOL><DEDENT>data.append(p)<EOL><DEDENT>df = pd.DataFrame.from_records(data)<EOL>df.sort_values('<STR_LIT>', inplace=True, kind='<STR_LIT>')<EOL>df = sportsref.nba.pbp.clean_features(df)<EOL>away, home = self.away(), self.home()<EOL>df['<STR_LIT>'] = home<EOL>df['<STR_LIT>'] = away<EOL>df['<STR_LIT>'] = self.boxscore_id<EOL>df['<STR_LIT>'] = self.season()<EOL>date = self.date()<EOL>df['<STR_LIT>'] = date.year<EOL>df['<STR_LIT>'] = date.month<EOL>df['<STR_LIT>'] = date.day<EOL>def _clean_rebs(df):<EOL><INDENT>df.reset_index(drop=True, inplace=True)<EOL>no_reb_after = (<EOL>(df.fta_num < df.tot_fta) | df.is_ftm |<EOL>df.get('<STR_LIT>', False)<EOL>).shift(<NUM_LIT:1>).fillna(False)<EOL>no_reb_before = (<EOL>(df.fta_num == df.tot_fta)<EOL>).shift(-<NUM_LIT:1>).fillna(False)<EOL>se_end_qtr = df.loc[<EOL>df.clock_time == '<STR_LIT>', '<STR_LIT>'<EOL>].unique()<EOL>no_reb_when = df.secs_elapsed.isin(se_end_qtr)<EOL>drop_mask = (<EOL>(df.rebounder == '<STR_LIT>') &<EOL>(no_reb_after | no_reb_before | no_reb_when)<EOL>).nonzero()[<NUM_LIT:0>]<EOL>df.drop(drop_mask, axis=<NUM_LIT:0>, inplace=True)<EOL>df.reset_index(drop=True, inplace=True)<EOL>return df<EOL><DEDENT>df = _clean_rebs(df)<EOL>new_poss = (df.off_team == df.home).diff().fillna(False)<EOL>df['<STR_LIT>'] = np.cumsum(new_poss) + df.is_dreb<EOL>poss_id_reb = np.cumsum(new_poss | df.is_reb)<EOL>sort_cols = [col for col in<EOL>['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>',<EOL>'<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>',<EOL>'<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']<EOL>if col in df.columns]<EOL>asc_true = ['<STR_LIT>']<EOL>ascend = [(col in asc_true) for col in sort_cols]<EOL>for label, group in df.groupby([df.secs_elapsed, poss_id_reb]):<EOL><INDENT>if len(group) > <NUM_LIT:1>:<EOL><INDENT>df.loc[group.index, :] = group.sort_values(<EOL>sort_cols, ascending=ascend, kind='<STR_LIT>'<EOL>).values<EOL><DEDENT><DEDENT>df = _clean_rebs(df)<EOL>df.loc[df['<STR_LIT>'], ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']] = np.nan<EOL>df.off_team.fillna(method='<STR_LIT>', inplace=True)<EOL>df.def_team.fillna(method='<STR_LIT>', inplace=True)<EOL>df.poss_id.fillna(method='<STR_LIT>', inplace=True)<EOL>if '<STR_LIT>' in df.columns:<EOL><INDENT>df.loc[df['<STR_LIT>'], ['<STR_LIT>', '<STR_LIT>']] = np.nan<EOL><DEDENT>if '<STR_LIT>' in df.columns:<EOL><INDENT>tech_fta = df['<STR_LIT>']<EOL>df.loc[tech_fta, '<STR_LIT>'] = df.loc[tech_fta, '<STR_LIT>']<EOL>df.loc[tech_fta, '<STR_LIT>'] = np.where(<EOL>df.loc[tech_fta, '<STR_LIT>'] == home, away, home<EOL>)<EOL><DEDENT>df.drop('<STR_LIT>', axis=<NUM_LIT:1>, inplace=True)<EOL>new_poss = (df.off_team == df.home).diff().fillna(False)<EOL>poss_id_reb = np.cumsum(new_poss | df.is_reb)<EOL>for (se, tm, pnum), group in df[df.is_sub].groupby(<EOL>[df.secs_elapsed, df.sub_team, poss_id_reb]<EOL>):<EOL><INDENT>if len(group) > <NUM_LIT:1>:<EOL><INDENT>sub_in = set()<EOL>sub_out = set()<EOL>for i, row in group.iterrows():<EOL><INDENT>if row['<STR_LIT>'] in sub_out:<EOL><INDENT>sub_out.remove(row['<STR_LIT>'])<EOL><DEDENT>else:<EOL><INDENT>sub_in.add(row['<STR_LIT>'])<EOL><DEDENT>if row['<STR_LIT>'] in sub_in:<EOL><INDENT>sub_in.remove(row['<STR_LIT>'])<EOL><DEDENT>else:<EOL><INDENT>sub_out.add(row['<STR_LIT>'])<EOL><DEDENT><DEDENT>assert len(sub_in) == len(sub_out)<EOL>n_subs = len(sub_in)<EOL>for idx, p_in, p_out in zip(<EOL>group.index[:n_subs], sub_in, sub_out<EOL>):<EOL><INDENT>assert df.loc[idx, '<STR_LIT>']<EOL>df.loc[idx, '<STR_LIT>'] = p_in<EOL>df.loc[idx, '<STR_LIT>'] = p_out<EOL>df.loc[idx, '<STR_LIT>'] = tm<EOL>df.loc[idx, '<STR_LIT>'] = (<EOL>'<STR_LIT>'.format(p_in, p_out)<EOL>)<EOL><DEDENT>n_extra = len(group) - len(sub_in)<EOL>if n_extra:<EOL><INDENT>extra_idxs = group.index[-n_extra:]<EOL>df.drop(extra_idxs, axis=<NUM_LIT:0>, inplace=True)<EOL><DEDENT><DEDENT><DEDENT>df.reset_index(drop=True, inplace=True)<EOL>df['<STR_LIT>'] = (df['<STR_LIT>'] + <NUM_LIT:2> * df['<STR_LIT>'] +<EOL>(df['<STR_LIT>'] & df['<STR_LIT>']))<EOL>df['<STR_LIT>'] = np.where(df.off_team == df.home, df.pts, <NUM_LIT:0>)<EOL>df['<STR_LIT>'] = np.where(df.off_team == df.away, df.pts, <NUM_LIT:0>)<EOL>df['<STR_LIT>'] = np.cumsum(df['<STR_LIT>'])<EOL>df['<STR_LIT>'] = np.cumsum(df['<STR_LIT>'])<EOL>new_qtr = df.quarter.diff().shift(-<NUM_LIT:1>).fillna(False).astype(bool)<EOL>and1 = (df.is_fgm & df.is_pf.shift(-<NUM_LIT:1>).fillna(False) &<EOL>df.is_fta.shift(-<NUM_LIT:2>).fillna(False) &<EOL>~df.secs_elapsed.diff().shift(-<NUM_LIT:1>).fillna(False).astype(bool))<EOL>double_lane = (df.get('<STR_LIT>') == '<STR_LIT>')<EOL>new_play = df.eval('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL>df['<STR_LIT>'] = np.cumsum(new_play).shift(<NUM_LIT:1>).fillna(<NUM_LIT:0>)<EOL>df['<STR_LIT>'] = df.off_team == df.home<EOL>if dense_lineups:<EOL><INDENT>df = pd.concat(<EOL>(df, sportsref.nba.pbp.get_dense_lineups(df)), axis=<NUM_LIT:1><EOL>)<EOL><DEDENT>if sparse_lineups:<EOL><INDENT>df = pd.concat(<EOL>(df, sportsref.nba.pbp.get_sparse_lineups(df)), axis=<NUM_LIT:1><EOL>)<EOL><DEDENT>return df<EOL>

Returns a dataframe of the play-by-play data from the game.

        :param dense_lineups: If True, adds 10 columns containing the names of
            the players on the court. Defaults to False.
        :param sparse_lineups: If True, adds binary columns denoting whether a
            given player is in the game at the time of a pass. Defaults to
            False.
        :returns: pandas DataFrame of play-by-play. Similar to GPF.


doc = self.get_main_doc()<EOL>name = doc('<STR_LIT>').text()<EOL>return name<EOL>

Returns the real name of the franchise given the team ID.

        Examples:
        'BOS' -> 'Boston Celtics'
        'NJN' -> 'Brooklyn Nets'

        :returns: A string corresponding to the team's full name.


doc = self.get_year_doc(year)<EOL>table = doc('<STR_LIT>')<EOL>df = sportsref.utils.parse_table(table)<EOL>df['<STR_LIT>'] = (df['<STR_LIT>']<EOL>.replace('<STR_LIT:R>', <NUM_LIT:0>).replace('<STR_LIT>', np.nan).astype(float))<EOL>return df<EOL>

Returns the roster table for the given year.

        :year: The year for which we want the roster; defaults to current year.
        :returns: A DataFrame containing roster information for that year.


doc = self.get_year_doc('<STR_LIT>'.format(year))<EOL>table = doc('<STR_LIT>')<EOL>df = sportsref.utils.parse_table(table)<EOL>return df<EOL>

Gets schedule information for a team-season.

        :year: The year for which we want the schedule.
        :returns: DataFrame of schedule information.


def parse_play(boxscore_id, details, is_hm):

<EOL>if not details or not isinstance(details, basestring):<EOL><INDENT>return None<EOL><DEDENT>bs = sportsref.nba.BoxScore(boxscore_id)<EOL>aw, hm = bs.away(), bs.home()<EOL>season = sportsref.nba.Season(bs.season())<EOL>hm_roster = set(bs.basic_stats().query('<STR_LIT>').player_id.values)<EOL>p = {}<EOL>p['<STR_LIT>'] = details<EOL>p['<STR_LIT>'] = hm<EOL>p['<STR_LIT>'] = aw<EOL>p['<STR_LIT>'] = is_hm<EOL>shotRE = (r'<STR_LIT>'<EOL>'<STR_LIT>').format(PLAYER_RE)<EOL>distRE = r'<STR_LIT>'<EOL>assistRE = r'<STR_LIT>'.format(PLAYER_RE)<EOL>blockRE = r'<STR_LIT>'.format(PLAYER_RE)<EOL>shotRE = r'<STR_LIT>'.format(shotRE, distRE, assistRE, blockRE)<EOL>m = re.match(shotRE, details, re.IGNORECASE)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] if p['<STR_LIT>'] is not None else <NUM_LIT:0><EOL>p['<STR_LIT>'] = int(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT:3>'<EOL>p['<STR_LIT>'] = pd.notnull(p.get('<STR_LIT>'))<EOL>p['<STR_LIT>'] = pd.notnull(p.get('<STR_LIT>'))<EOL>shooter_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if shooter_home else aw<EOL>p['<STR_LIT>'] = aw if shooter_home else hm<EOL>return p<EOL><DEDENT>jumpRE = ((r'<STR_LIT>'<EOL>r'<STR_LIT>')<EOL>.format(PLAYER_RE))<EOL>m = re.match(jumpRE, details, re.IGNORECASE)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>return p<EOL><DEDENT>rebRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(rebRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = p['<STR_LIT>'].lower() == '<STR_LIT>'<EOL>p['<STR_LIT>'] = not p['<STR_LIT>']<EOL>if p['<STR_LIT>'] == '<STR_LIT>':<EOL><INDENT>p['<STR_LIT>'], other = (hm, aw) if is_hm else (aw, hm)<EOL><DEDENT>else:<EOL><INDENT>reb_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'], other = (hm, aw) if reb_home else (aw, hm)<EOL><DEDENT>p['<STR_LIT>'] = p['<STR_LIT>'] if p['<STR_LIT>'] else other<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] if p['<STR_LIT>'] else other<EOL>return p<EOL><DEDENT>ftRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(ftRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = not p['<STR_LIT>']<EOL>if p['<STR_LIT>']:<EOL><INDENT>p['<STR_LIT>'] = int(p['<STR_LIT>'])<EOL><DEDENT>if p['<STR_LIT>']:<EOL><INDENT>p['<STR_LIT>'] = int(p['<STR_LIT>'])<EOL><DEDENT>ft_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if ft_home else aw<EOL>if not p['<STR_LIT>']:<EOL><INDENT>p['<STR_LIT>'] = hm if ft_home else aw<EOL>p['<STR_LIT>'] = aw if ft_home else hm<EOL><DEDENT>return p<EOL><DEDENT>subRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(subRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>sub_home = p['<STR_LIT>'] in hm_roster or p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if sub_home else aw<EOL>return p<EOL><DEDENT>toReasons = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>toRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE, toReasons)<EOL>m = re.match(toRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = p['<STR_LIT>'].lower()<EOL>if p['<STR_LIT>'] == '<STR_LIT>':<EOL><INDENT>return None<EOL><DEDENT>p['<STR_LIT>'] = pd.notnull(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>p['<STR_LIT>'] = p['<STR_LIT>'] == '<STR_LIT>'<EOL>if p['<STR_LIT>'] == '<STR_LIT>':<EOL><INDENT>p['<STR_LIT>'] = hm if is_hm else aw<EOL>p['<STR_LIT>'] = aw if is_hm else hm<EOL><DEDENT>else:<EOL><INDENT>to_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if to_home else aw<EOL>p['<STR_LIT>'] = aw if to_home else hm<EOL><DEDENT>return p<EOL><DEDENT>shotFoulRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(shotFoulRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = aw if foul_on_home else hm<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL>return p<EOL><DEDENT>offFoulRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(offFoulRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = '<STR_LIT>'<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>p['<STR_LIT>'] = aw if foul_on_home else hm<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL>return p<EOL><DEDENT>foulRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(foulRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = aw if foul_on_home else hm<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL>return p<EOL><DEDENT>looseBallRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(looseBallRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>foul_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if foul_home else aw<EOL>return p<EOL><DEDENT>awayFromBallRE = ((r'<STR_LIT>'<EOL>r'<STR_LIT>')<EOL>.format(PLAYER_RE))<EOL>m = re.match(awayFromBallRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>return p<EOL><DEDENT>inboundRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(inboundRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = aw if foul_on_home else hm<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL>return p<EOL><DEDENT>flagrantRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(flagrantRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>return p<EOL><DEDENT>clearPathRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(clearPathRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = aw if foul_on_home else hm<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL>return p<EOL><DEDENT>timeoutRE = r'<STR_LIT>'<EOL>m = re.match(timeoutRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>isOfficialTO = p['<STR_LIT>'].lower() == '<STR_LIT>'<EOL>name_to_id = season.team_names_to_ids()<EOL>p['<STR_LIT>'] = (<EOL>'<STR_LIT>' if isOfficialTO else<EOL>name_to_id.get(hm, name_to_id.get(aw, p['<STR_LIT>']))<EOL>)<EOL>return p<EOL><DEDENT>techRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(techRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>p['<STR_LIT>'] = bool(p['<STR_LIT>'])<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>return p<EOL><DEDENT>ejectRE = r'<STR_LIT>'.format(PLAYER_RE)<EOL>m = re.match(ejectRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>if p['<STR_LIT>'] == '<STR_LIT>':<EOL><INDENT>p['<STR_LIT>'] = hm if is_hm else aw<EOL><DEDENT>else:<EOL><INDENT>eject_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if eject_home else aw<EOL><DEDENT>return p<EOL><DEDENT>def3TechRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(def3TechRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>foul_on_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = aw if foul_on_home else hm<EOL>p['<STR_LIT>'] = hm if foul_on_home else aw<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL>return p<EOL><DEDENT>violRE = (r'<STR_LIT>'<EOL>r'<STR_LIT>').format(PLAYER_RE)<EOL>m = re.match(violRE, details, re.I)<EOL>if m:<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p.update(m.groupdict())<EOL>if p['<STR_LIT>'] == '<STR_LIT>':<EOL><INDENT>p['<STR_LIT>'] = True<EOL>p['<STR_LIT>'] = p['<STR_LIT>']<EOL><DEDENT>if p['<STR_LIT>'] == '<STR_LIT>':<EOL><INDENT>p['<STR_LIT>'] = hm if is_hm else aw<EOL><DEDENT>else:<EOL><INDENT>viol_home = p['<STR_LIT>'] in hm_roster<EOL>p['<STR_LIT>'] = hm if viol_home else aw<EOL><DEDENT>return p<EOL><DEDENT>p['<STR_LIT>'] = True<EOL>return p<EOL>

Parse play details from a play-by-play string describing a play.

    Assuming valid input, this function returns structured data in a dictionary
    describing the play. If the play detail string was invalid, this function
    returns None.

    :param boxscore_id: the boxscore ID of the play
    :param details: detail string for the play
    :param is_hm: bool indicating whether the offense is at home
    :param returns: dictionary of play attributes or None if invalid
    :rtype: dictionary or None


df = pd.DataFrame(df)<EOL>bool_vals = set([True, False, None, np.nan])<EOL>sparse_cols = sparse_lineup_cols(df)<EOL>for col in df:<EOL><INDENT>if set(df[col].unique()[:<NUM_LIT:5>]) <= bool_vals:<EOL><INDENT>df[col] = (df[col] == True)<EOL><DEDENT>elif col in sparse_cols:<EOL><INDENT>df[col] = df[col].fillna(<NUM_LIT:0>)<EOL><DEDENT><DEDENT>df.loc[df.is_tech_fta, ['<STR_LIT>', '<STR_LIT>']] = <NUM_LIT:1><EOL>df.off_team.fillna(method='<STR_LIT>', inplace=True)<EOL>df.def_team.fillna(method='<STR_LIT>', inplace=True)<EOL>df.off_team.fillna(method='<STR_LIT>', inplace=True)<EOL>df.def_team.fillna(method='<STR_LIT>', inplace=True)<EOL>return df<EOL>

Fixes up columns of the passed DataFrame, such as casting T/F columns to
    boolean and filling in NaNs for team and opp.

    :param df: DataFrame of play-by-play data.
    :returns: Dataframe with cleaned columns.


df = pd.DataFrame(df)<EOL>if df.index.value_counts().max() > <NUM_LIT:1>:<EOL><INDENT>df.reset_index(drop=True, inplace=True)<EOL><DEDENT>df = clean_features(df)<EOL>for col in ('<STR_LIT>', '<STR_LIT>'):<EOL><INDENT>diffs = df[col].diff().fillna(<NUM_LIT:0>)<EOL>if (diffs < <NUM_LIT:0>).any():<EOL><INDENT>new_col = np.cumsum(diffs.astype(bool))<EOL>df.eval('<STR_LIT>'.format(col), inplace=True)<EOL><DEDENT><DEDENT>return df<EOL>

TODO: Docstring for clean_multigame_features.

    :df: TODO
    :returns: TODO


def players_from_play(play):<EOL><INDENT>"""<STR_LIT>"""<EOL>if (<EOL>play['<STR_LIT>'] == '<STR_LIT>' and<EOL>(play.get('<STR_LIT>') or play.get('<STR_LIT>'))<EOL>):<EOL><INDENT>return [], []<EOL><DEDENT>stats = sportsref.nba.BoxScore(play['<STR_LIT>']).basic_stats()<EOL>home_grouped = stats.groupby('<STR_LIT>')<EOL>hm_roster = set(home_grouped.player_id.get_group(True).values)<EOL>aw_roster = set(home_grouped.player_id.get_group(False).values)<EOL>player_keys = [<EOL>'<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>',<EOL>'<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>',<EOL>'<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>'<EOL>]<EOL>players = [p for p in play[player_keys] if pd.notnull(p)]<EOL>aw_players = [p for p in players if p in aw_roster]<EOL>hm_players = [p for p in players if p in hm_roster]<EOL>return aw_players, hm_players<EOL><DEDENT>n_periods = df.quarter.nunique()<EOL>period_starters = [(set(), set()) for _ in range(n_periods)]<EOL>for qtr, qtr_grp in df.groupby(df.quarter):<EOL><INDENT>aw_starters, hm_starters = period_starters[qtr-<NUM_LIT:1>]<EOL>exclude = set()<EOL>for label, time_grp in qtr_grp.groupby(qtr_grp.secs_elapsed):<EOL><INDENT>sub_ins = set(time_grp.sub_in.dropna().values)<EOL>exclude.update(sub_ins - aw_starters - hm_starters)<EOL>for i, row in time_grp.iterrows():<EOL><INDENT>aw_players, hm_players = players_from_play(row)<EOL>aw_starters.update(aw_players)<EOL>hm_starters.update(hm_players)<EOL><DEDENT>hm_starters -= exclude<EOL>aw_starters -= exclude<EOL>if len(hm_starters) > <NUM_LIT:5> or len(aw_starters) > <NUM_LIT:5>:<EOL><INDENT>import ipdb<EOL>ipdb.set_trace()<EOL><DEDENT>if len(hm_starters) >= <NUM_LIT:5> and len(aw_starters) >= <NUM_LIT:5>:<EOL><INDENT>break<EOL><DEDENT><DEDENT>if len(hm_starters) != <NUM_LIT:5> or len(aw_starters) != <NUM_LIT:5>:<EOL><INDENT>print('<STR_LIT>'<EOL>.format(qtr, df.boxscore_id.iloc[<NUM_LIT:0>]))<EOL><DEDENT><DEDENT>return period_starters<EOL>


<EOL>if (set(ALL_LINEUP_COLS) - set(df.columns)):<EOL><INDENT>lineup_df = get_dense_lineups(df)<EOL><DEDENT>else:<EOL><INDENT>lineup_df = df[ALL_LINEUP_COLS]<EOL><DEDENT>hm_lineups = lineup_df[HM_LINEUP_COLS].values<EOL>aw_lineups = lineup_df[AW_LINEUP_COLS].values<EOL>hm_df = pd.DataFrame([<EOL>{'<STR_LIT>'.format(player_id): <NUM_LIT:1> for player_id in lineup}<EOL>for lineup in hm_lineups<EOL>], dtype=int)<EOL>aw_df = pd.DataFrame([<EOL>{'<STR_LIT>'.format(player_id): -<NUM_LIT:1> for player_id in lineup}<EOL>for lineup in aw_lineups<EOL>], dtype=int)<EOL>sparse_df = pd.concat((hm_df, aw_df), axis=<NUM_LIT:1>).fillna(<NUM_LIT:0>)<EOL>return sparse_df<EOL>

TODO: Docstring for get_sparse_lineups.

    :param df: TODO
    :returns: TODO


<EOL>assert df['<STR_LIT>'].nunique() == <NUM_LIT:1><EOL>def lineup_dict(aw_lineup, hm_lineup):<EOL><INDENT>"""<STR_LIT>"""<EOL>return {<EOL>'<STR_LIT>'.format(tm, i+<NUM_LIT:1>): player<EOL>for tm, lineup in zip(['<STR_LIT>', '<STR_LIT>'], [aw_lineup, hm_lineup])<EOL>for i, player in enumerate(lineup)<EOL>}<EOL><DEDENT>def handle_sub(row, aw_lineup, hm_lineup):<EOL><INDENT>"""<STR_LIT>"""<EOL>assert row['<STR_LIT>']<EOL>sub_lineup = hm_lineup if row['<STR_LIT>'] == row['<STR_LIT>'] else aw_lineup<EOL>try:<EOL><INDENT>idx = sub_lineup.index(row['<STR_LIT>'])<EOL>sub_lineup[idx] = row['<STR_LIT>']<EOL><DEDENT>except ValueError:<EOL><INDENT>if (<EOL>row['<STR_LIT>'] in sub_lineup<EOL>and row['<STR_LIT>'] not in sub_lineup<EOL>):<EOL><INDENT>return aw_lineup, hm_lineup<EOL><DEDENT>print('<STR_LIT>'<EOL>.format(row['<STR_LIT>'], row['<STR_LIT>'],<EOL>row['<STR_LIT>'], row['<STR_LIT>']))<EOL>raise<EOL><DEDENT>return aw_lineup, hm_lineup<EOL><DEDENT>per_starters = get_period_starters(df)<EOL>cur_qtr = <NUM_LIT:0><EOL>aw_lineup, hm_lineup = [], []<EOL>df = df.reset_index(drop=True)<EOL>lineups = [{} for _ in range(df.shape[<NUM_LIT:0>])]<EOL>sub_or_per_start = df.is_sub | df.quarter.diff().astype(bool)<EOL>for i, row in df.loc[sub_or_per_start].iterrows():<EOL><INDENT>if row['<STR_LIT>'] > cur_qtr:<EOL><INDENT>assert row['<STR_LIT>'] == cur_qtr + <NUM_LIT:1><EOL>if cur_qtr > <NUM_LIT:0> and not df.loc[i-<NUM_LIT:1>, '<STR_LIT>']:<EOL><INDENT>lineups[i-<NUM_LIT:1>] = lineup_dict(aw_lineup, hm_lineup)<EOL><DEDENT>cur_qtr += <NUM_LIT:1><EOL>aw_lineup, hm_lineup = map(list, per_starters[cur_qtr-<NUM_LIT:1>])<EOL>lineups[i] = lineup_dict(aw_lineup, hm_lineup)<EOL>if row['<STR_LIT>']:<EOL><INDENT>aw_lineup, hm_lineup = handle_sub(row, aw_lineup, hm_lineup)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>lineups[i] = lineup_dict(aw_lineup, hm_lineup)<EOL>if row['<STR_LIT>']:<EOL><INDENT>aw_lineup, hm_lineup = handle_sub(row, aw_lineup, hm_lineup)<EOL><DEDENT><DEDENT><DEDENT>lineup_df = pd.DataFrame(lineups)<EOL>if lineup_df.iloc[-<NUM_LIT:1>].isnull().all():<EOL><INDENT>lineup_df.iloc[-<NUM_LIT:1>] = lineup_dict(aw_lineup, hm_lineup)<EOL><DEDENT>lineup_df = lineup_df.groupby(df.quarter).fillna(method='<STR_LIT>')<EOL>bool_mat = lineup_df.isnull()<EOL>mask = bool_mat.any(axis=<NUM_LIT:1>)<EOL>if mask.any():<EOL><INDENT>bs = sportsref.nba.BoxScore(df.boxscore_id[<NUM_LIT:0>])<EOL>stats = sportsref.nba.BoxScore(df.boxscore_id.iloc[<NUM_LIT:0>]).basic_stats()<EOL>true_mp = pd.Series(<EOL>stats.query('<STR_LIT>')[['<STR_LIT>', '<STR_LIT>']]<EOL>.set_index('<STR_LIT>').to_dict()['<STR_LIT>']<EOL>) * <NUM_LIT><EOL>calc_mp = pd.Series(<EOL>{p: (df.secs_elapsed.diff() *<EOL>[p in row for row in lineup_df.values]).sum()<EOL>for p in stats.query('<STR_LIT>').player_id.values})<EOL>diff = true_mp - calc_mp<EOL>players_missing = diff.loc[diff.abs() >= <NUM_LIT>]<EOL>hm_roster = bs.basic_stats().query('<STR_LIT>').player_id.values<EOL>missing_df = pd.DataFrame(<EOL>{'<STR_LIT>': players_missing.values,<EOL>'<STR_LIT>': players_missing.index.isin(hm_roster)},<EOL>index=players_missing.index<EOL>)<EOL>if missing_df.empty:<EOL><INDENT>print('<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>for is_home, group in missing_df.groupby('<STR_LIT>'):<EOL><INDENT>player_id = group.index.item()<EOL>tm_cols = (sportsref.nba.pbp.HM_LINEUP_COLS if is_home else<EOL>sportsref.nba.pbp.AW_LINEUP_COLS)<EOL>row_mask = lineup_df[tm_cols].isnull().any(axis=<NUM_LIT:1>)<EOL>lineup_df.loc[row_mask, tm_cols] = (<EOL>lineup_df.loc[row_mask, tm_cols].fillna(player_id).values<EOL>)<EOL><DEDENT><DEDENT><DEDENT>return lineup_df<EOL>

Returns a new DataFrame based on the one it is passed. Specifically, it
    adds five columns for each team (ten total), where each column has the ID
    of a player on the court during the play.

    This information is figured out sequentially from the game's substitution
    data in the passed DataFrame, so the DataFrame passed as an argument must
    be from a specific BoxScore (rather than a DataFrame of non-consecutive
    plays). That is, the DataFrame must be of the form returned by
    :func:`nba.BoxScore.pbp <nba.BoxScore.pbp>`.

    .. note:: Note that the lineups reflect the teams in the game when the play
        happened, not after the play. For example, if a play is a substitution,
        the lineups for that play will be the lineups before the substituion
        occurs.

    :param df: A DataFrame of a game's play-by-play data.
    :returns: A DataFrame with additional lineup columns.


self.yr = int(year)<EOL>

Initializes a Season object for an NFL season.

        :year: The year of the season we want.


url = sportsref.nfl.BASE_URL + '<STR_LIT>'.format(self.yr)<EOL>return pq(sportsref.utils.get_html(url))<EOL>

Returns PyQuery object for the main season URL.
        :returns: PyQuery object.


html = sportsref.utils.get_html(self._subpage_url(subpage))<EOL>return pq(html)<EOL>

Returns PyQuery object for a given subpage URL.
        :subpage: The subpage of the season, e.g. 'per_game'.
        :returns: PyQuery object.


return sportsref.nfl.teams.list_teams(self.yr)<EOL>

Returns a list of the team IDs for the given year.
        :returns: List of team IDs.


return sportsref.nfl.teams.team_names(self.yr)<EOL>

Mapping from 3-letter team IDs to full team names.

        :returns: Dictionary with team IDs as keys and full team strings as
            values.


return sportsref.nfl.teams.team_ids(self.yr)<EOL>

Mapping from full team names to 3-letter team IDs.
        :returns: Dictionary with tean names as keys and team IDs as values.


@sportsref.decorators.memoize<EOL><INDENT>def _get_player_stats_table(self, subpage, table_id):<DEDENT>

doc = self.get_sub_doc(subpage)<EOL>table = doc('<STR_LIT>'.format(table_id))<EOL>df = sportsref.utils.parse_table(table)<EOL>return df<EOL>

Helper function for player season stats.

        :identifier: string identifying the type of stat, e.g. 'passing'.
        :returns: A DataFrame of stats.


return self._get_player_stats_table('<STR_LIT>', '<STR_LIT>')<EOL>

Returns a DataFrame of passing player stats for a season.


Returns a DataFrame of rushing player stats for a season.


Returns a DataFrame of receiving player stats for a season.


url = self._subpage_url('<STR_LIT>', None)  <EOL>doc = pq(sportsref.utils.get_html(url))<EOL>table = (doc('<STR_LIT>') if kind == '<STR_LIT:R>' else<EOL>doc('<STR_LIT>'))<EOL>df = sportsref.utils.parse_table(table)<EOL>if year is not None:<EOL><INDENT>df = df.query('<STR_LIT>').reset_index(drop=True)<EOL><DEDENT>return df<EOL>

Gets the career gamelog of the given player.
        :kind: One of 'R', 'P', or 'B' (for regular season, playoffs, or both).
        Case-insensitive; defaults to 'R'.
        :year: The year for which the gamelog should be returned; if None,
        return entire career gamelog. Defaults to None.
        :returns: A DataFrame with the player's career gamelog.


doc = self.get_doc()<EOL>table = (doc('<STR_LIT>') if kind == '<STR_LIT:R>' else<EOL>doc('<STR_LIT>'))<EOL>df = sportsref.utils.parse_table(table)<EOL>return df<EOL>

Gets yearly passing stats for the player.

        :kind: One of 'R', 'P', or 'B'. Case-insensitive; defaults to 'R'.
        :returns: Pandas DataFrame with passing stats.


doc = self.get_doc()<EOL>table = (doc('<STR_LIT>') if kind == '<STR_LIT:R>'<EOL>else doc('<STR_LIT>'))<EOL>if not table:<EOL><INDENT>table = (doc('<STR_LIT>') if kind == '<STR_LIT:R>'<EOL>else doc('<STR_LIT>'))<EOL><DEDENT>df = sportsref.utils.parse_table(table)<EOL>return df<EOL>

Gets yearly rushing/receiving stats for the player.

        :kind: One of 'R', 'P', or 'B'. Case-insensitive; defaults to 'R'.
        :returns: Pandas DataFrame with rushing/receiving stats.


Gets yearly defense stats for the player (also has AV stats for OL).

        :kind: One of 'R', 'P', or 'B'. Case-insensitive; defaults to 'R'.
        :returns: Pandas DataFrame with rushing/receiving stats.


def _plays(self, year, play_type, expand_details):

url = self._subpage_url('<STR_LIT>'.format(play_type), year)<EOL>doc = pq(sportsref.utils.get_html(url))<EOL>table = doc('<STR_LIT>')<EOL>if table:<EOL><INDENT>if expand_details:<EOL><INDENT>plays = sportsref.nfl.pbp.expand_details(<EOL>sportsref.utils.parse_table(table), detailCol='<STR_LIT:description>'<EOL>)<EOL>return plays<EOL><DEDENT>else:<EOL><INDENT>return sportsref.utils.parse_table(table)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT>

Returns a DataFrame of plays for a given year for a given play type
        (like rushing, receiving, or passing).

        :year: The year for the season.
        :play_type: A type of play for which there are plays (as of this
        writing, either "passing", "rushing", or "receiving")
        :expand_details: Bool for whether PBP should be parsed.
        :returns: A DataFrame of plays, each row is a play. Returns None if
        there were no such plays in that year.


@sportsref.decorators.memoize<EOL><INDENT>def passing_plays(self, year, expand_details=True):<DEDENT>

return self._plays(year, '<STR_LIT>', expand_details)<EOL>

Returns a pbp DataFrame of a player's passing plays in a season.

        :year: The year for the season.
        :expand_details: bool for whether PBP should be parsed.
        :returns: A DataFrame of stats, each row is a play.


@sportsref.decorators.memoize<EOL><INDENT>def rushing_plays(self, year, expand_details=True):<DEDENT>

Returns a pbp DataFrame of a player's rushing plays in a season.

        :year: The year for the season.
        :expand_details: bool for whether PBP should be parsed.
        :returns: A DataFrame of stats, each row is a play.


@sportsref.decorators.memoize<EOL><INDENT>def receiving_plays(self, year, expand_details=True):<DEDENT>

Returns a pbp DataFrame of a player's receiving plays in a season.

        :year: The year for the season.
        :expand_details: bool for whether PBP should be parsed.
        :returns: A DataFrame of stats, each row is a play.


<EOL>url = self._subpage_url('<STR_LIT>', year)<EOL>doc = pq(sportsref.utils.get_html(url))<EOL>table = doc('<STR_LIT>')<EOL>df = sportsref.utils.parse_table(table)<EOL>if not df.empty:<EOL><INDENT>df.split_id.fillna(method='<STR_LIT>', inplace=True)<EOL><DEDENT>return df<EOL>

Returns a DataFrame of splits data for a player-year.

        :year: The year for the season in question. If None, returns career
        splits.
        :returns: A DataFrame of splits data.


<EOL>url = self._subpage_url('<STR_LIT>', year)<EOL>doc = pq(sportsref.utils.get_html(url))<EOL>table = doc('<STR_LIT>')<EOL>df = sportsref.utils.parse_table(table)<EOL>if not df.empty:<EOL><INDENT>df.split_type.fillna(method='<STR_LIT>', inplace=True)<EOL><DEDENT>return df<EOL>

Returns a DataFrame of advanced splits data for a player-year. Note:
            only go back to 2012.

        :year: The year for the season in question. If None, returns career
        advanced splits.
        :returns: A DataFrame of advanced splits data.