pci工具代码

"""
    2018-10-17至30
    作者:王涵
    微信:18843112066
    邮箱:[email protected]
"""
import datetime

import xlrd
import pandas as pd
import numpy as np
from django.core.exceptions import MultipleObjectsReturned
from django.db.models import Model, Count, F, Q, Case, When
from geographiclib.geodesic import Geodesic

from dbbackend.models import ZJcell, LngLat, ZJenb, ZJadjacent


class Cellinforeader:
    """读取excel的类"""

    def __init__(self, path=r'C:\Users\Administrator\Desktop\嘉兴工参\圈定区域网内邻区关系(1).xlsx', sheetname='圈定小区'):
        try:
            self.workbook = xlrd.open_workbook(path)
            self.sheet = self.workbook.sheet_by_name(sheetname)
        except Exception as e:
            print(repr(e))
        # 列名与列号字典,例如{'小区名称':2}
        self.col_dict = {}
        # 如果邻区表中有个cgi在小区工参里没找到,就无法添加邻区,把这样的cgi过滤出来保留以便后续使用
        self.mismatchedcells = dict()
        self.mismatchedcgis = []
        # self.mismatchedcgi_t = dict()
        self.mismatchedrowid = []
        # sheet.ncols:  Nominal number of columns in sheet.
        for i in range(self.sheet.ncols):
            self.col_dict[self.alltypestrip(self.sheet.cell_value(0, i))] = i
            # ' abc '.strip()去除字符串前后的空格

    # 提取每行数据,导入小区数据库ZJcell中
    def insertcells(self, eci='ECGI', cgi='CGI', cellname='小区名称', freq='频段', pci='PCID', lng='基站经度',
                    lat='基站纬度', azimuth='扇区方位角', enbname='基站名称', enbid='LTEENODEBID', cellid='小区标识'):
        insertcount = 0
        for i in range(1, self.sheet.nrows):
            row = self.sheet.row_values(i)
            # 下面啰嗦了这么多行,无非是要实现两个功能,一是根据列名寻找数据,避免根据列的位置寻找数据时格式不能改
            # 二是利用strip函数将字符串前后的空格删除,避免基站名后面带空格的情况,这里利用的小技巧有:
            # 1、把列名和列号做成dict,这样就可直接通过列名取列号,比循环查找函数省时间
            # 2、alltypestrip()函数利用了python三目运算
            # 3、因为变量名重复,所以在结果的变量名前加下划线 _ ,加以区分
            # 4、这么多重复的写法,看似可以使用循环来解决,但那样反而复杂,不如使用相同的格式列出来,以后看着清晰,
            #    相当于配置的赋值都应该这样写
            _eci = self.alltypestrip(row[self.col_dict[eci]])
            _cellid = self.alltypestrip(row[self.col_dict[cellid]])
            _enbname = self.alltypestrip(row[self.col_dict[enbname]])
            _enbid = self.alltypestrip(row[self.col_dict[enbid]])
            _lng = self.alltypestrip(row[self.col_dict[lng]])
            _lat = self.alltypestrip(row[self.col_dict[lat]])
            _cgi = self.alltypestrip(row[self.col_dict[cgi]])
            _cellname = self.alltypestrip(row[self.col_dict[cellname]])
            _freq = self.alltypestrip(row[self.col_dict[freq]])
            _pci = self.alltypestrip(row[self.col_dict[pci]])
            _azimuth = self.alltypestrip(row[self.col_dict[azimuth]])
            # 这个变量用于标识读取的一行excel数据用get_or_create创建时,是否已存在,
            # 如果数据库中不存在,就在数据库中创建一条数据,返回值中的元组的第二项设为True,
            createdornot2 = None
            try:
                enb, createdornot = ZJenb.objects.get_or_create(enbname=_enbname, enbid=_enbid)
                lnglat, createdornot1 = LngLat.objects.get_or_create(lng=_lng, lat=_lat)
                cell, createdornot2 = ZJcell.objects.get_or_create(eci=_eci, cgi=_cgi, cellname=_cellname, freq=_freq,
                                                                   pci=_pci, azimuth=_azimuth, lnglat=lnglat, enb=enb,
                                                                   cellid=_cellid)
            # ' abc '.strip()去除字符串前后的空格
            except Exception as e:
                print(repr(e))
                print('插入小区工参时报错,可能与数据库有关,第' + str(i) + '行,小区名' + str(_cellname))

            # get_or_create函数返回元组的第二个数据表示是否新创建了一条数据
            if createdornot2:
                insertcount += 1
        print("导入" + str(insertcount) + "条数据")

    # 对enbid 'float' object使用strip函数时报错,所以增加这个函数,使用strip前判断一下是不是str类型。
    @staticmethod
    def alltypestrip(args):
        return args.strip() if type(args) is str else args

    # 插入邻区关系
    def insertadj(self, scgi='本地小区CGI', tcgi='邻小区CGI'):
        insertcount = 0
        starttime = datetime.datetime.now()
        for i in range(1, self.sheet.nrows):
            if i % 2000 == 0:
                delta = datetime.datetime.now() - starttime
                print('正在录入第'+str(i)+'行,用时'+str(delta))
            row = self.sheet.row_values(i)
            _scgi = self.alltypestrip(row[self.col_dict[scgi]])
            _tcgi = self.alltypestrip(row[self.col_dict[tcgi]])
            # 如果源小区或目的小区查不到,将cgi写入数组中,后续将数据放入dict,用于输出
            mismatchedcgi = []
            # 按照cgi查找源小区和目的小区,用于后续建立多对多表
            source = None
            try:
                source = ZJcell.objects.get(cgi__exact=_scgi)
            except (ZJcell.DoesNotExist, MultipleObjectsReturned) as e:
                print(repr(e))
                print('小区工参表中没有找到第' + str(i) + '行源小区cgi,无法添加多对多邻区关系......:' + _scgi)
                mismatchedcgi.append(_scgi)
                # self.mismatchedcgi.update({str(i): _scgi})
            target = None
            try:
                target = ZJcell.objects.get(cgi__exact=_tcgi)
            except (ZJcell.DoesNotExist, MultipleObjectsReturned) as e:
                print(repr(e))
                print('小区工参表中没有找到第' + str(i) + '行目标小区cgi,无法添加多对多邻区关系....:' + _tcgi)
                mismatchedcgi.append(_tcgi)
                # self.mismatchedcgi_t.update({str(i): _tcgi})

            # 如果source和target中有一个为None,则不能添加邻区关系
            if source and target:
                '''
                # 以下代码因效率低而废弃
                # scgi_tcgi = source.cgi + '&' + target.cgi
                inverse_adj_set = None
                try:
                    # 查是否存在反向邻区,存在的话,将反向邻区的存在反向邻区指示改为True
                    inverse_adj_set = ZJadjacent.objects.filter(cellfrom=target, cellto=source)
                except Exception as e:
                    print(repr(e))
                    print('查反向邻区inverse_adj_set = ZJadjacent.objects.filter(cellfrom=target, cellto=source)报错')
                # 正向邻区关系的has_inverse_adj(是否存在反向邻区指示,True表示存在反向邻区,False表示不存在)
                has_inverse_adj = False
                # 如果存在反向邻区,将反向邻区的has_inverse_adj(存在反向邻区指示)改为True
                if inverse_adj_set:
                    # 不写save()的话,下面这种赋值方式不会修改数据库中的字段。
                    # inverse_adj_set.first().has_inverse_adj = True
                    inverse_adj_set.update(has_inverse_adj=True)  # not F('has_inverse_adj')
                    # 如果存在反向邻区关系,正向邻区关系的has_inverse_adj(存在反向邻区指示)也设为True
                    has_inverse_adj = True
                # 因为geodict1['azi1']的范围是从-180到+180,而通常的方位角是0到360,所以需要转换
                # geodict1['azi2']+180也是这个原因
                azi1 = geodict1['azi1']
                if azi1 < 0:
                    azi1 += 360
                '''
                # 计算两站之间距离和方位角
                geodict1 = Geodesic.WGS84.Inverse(source.lnglat.lat, source.lnglat.lng, target.lnglat.lat,
                                                  target.lnglat.lng)
                # 因为Geodesic.WGS84.Inverse输出的结果是-180到+180,需要转换成0到360
                azi1 = geodict1['azi1'] if geodict1['azi1'] >= 0 else geodict1['azi1'] + 360
                # Geodesic.WGS84.Inverse输出的azi2是1到2连线的方位角在2点的数值,当距离近时,地球近似为平面,所以基本与azi1一样
                # 想让azi2表示站在2点看1点的方位角,所以要加180,但不希望出现360度,所以使用下面的三目运算将360改为0
                azi2 = geodict1['azi2'] + 180 if geodict1['azi2'] != 180 else 0
                # source_target_cgi = 2 ** 32 * source.eci + target.eci主键是64bit,前32bit是源小区,后32bit是目标小区
                source_target_cgi = 2 ** 32 * source.eci + target.eci
                try:
                    adj, iscreated = ZJadjacent.objects.get_or_create(source_target_cgi=source_target_cgi,
                                                                      cellfrom=source, cellto=target,
                                                                      distance=round(geodict1['s12']),
                                                                      azi1=round(azi1),
                                                                      azi2=round(azi2))
                    # 如果是新创建的一条数据,就将计数器加1
                    if iscreated:
                        insertcount += 1
                    # source.adj.add(target)
                except Exception as e:
                    print(repr(e))
                    print('因ZJadjacent.objects.create报错,创建邻区关系失败:' + str(source) + '-' + str(target))
            else:
                self.mismatchedcgis.extend(mismatchedcgi)
                self.mismatchedrowid.append(i)
                self.mismatchedcells.update({str(i): {'source': _scgi, 'target': _tcgi, 'mismatched': mismatchedcgi}})
        print('共添加' + str(insertcount) + '条邻区')

    # 将所有不匹配的邻区中的cgi打印出来
    def mismatchedadj(self, path=r'J:\工参表里没有邻区表中cgi.xlsx'):
        df1 = pd.DataFrame(self.mismatchedcells).T
        df2 = pd.DataFrame({'工参中没有的cgi': self.mismatchedcgis})
        # subset='工参中没有的cgi' 表示只考虑列名为:工参中没有的cgi 这一列的重复项,不设则需考虑全部列,也可以设成多列
        # inplace=True是直接在df2表中删除重复项,如果设成inplace=False则不修改原表df2,而是返回去重后的新表
        df2.drop_duplicates(subset='工参中没有的cgi', inplace=True)
        with pd.ExcelWriter(path) as writer:
            df1.to_excel(writer, sheet_name='Sheet1')
            df2.to_excel(writer, sheet_name='Sheet2')

    # 计算邻区对之间的距离,原来在导入过程中计算距离,由于是逐条计算,而且邻区条数过多,80万条,导致效率低,运行缓慢
    # 这个函数先把同站点的邻区对的距离设为0,在通过批量计算相同经纬度之间的邻区对之间的距离,批量更新数据库
    # 实际跑发现效率不高,废弃
    '''
    @staticmethod
    def adjdistance():
        samesite = ZJadjacent.objects.filter(cellfrom__lnglat=F('cellto__lnglat'))
        affectedrows = samesite.update(distance=0, azi1=None, azi2=None)
        diffsite = ZJadjacent.objects.exclude(cellto__lnglat=F('cellfrom__lnglat'))
        affectedrows += Cellinforeader.recursive(diffsite)
        print('共更新' + str(affectedrows) + '行邻区数据的距离和方位角字段')

    # 通过递归调用实现批量计算邻区对之间的距离
    # 用Cellinforeader.recursive()来调用静态方法
    @staticmethod
    def recursive(queryset):
        if queryset.exists:
            adj1 = queryset.first()
            lnglat1 = adj1.cellfrom.lnglat
            lnglat2 = adj1.cellto.lnglat
            # 计算两站之间距离和方位角
            geodict1 = Geodesic.WGS84.Inverse(lnglat1.lat, lnglat1.lng, lnglat2.lat, lnglat2.lng)
            # 因为Geodesic.WGS84.Inverse输出的结果是-180到+180,需要转换成0到360
            azi1 = geodict1['azi1'] if geodict1['azi1'] >= 0 else geodict1['azi1'] + 360
            # Geodesic.WGS84.Inverse输出的azi2是1到2连线的方位角在2点的数值,当距离近时,地球近似为平面,所以基本与azi1一样
            # 想让azi2表示站在2点看1点的方位角,所以要加180,但不希望出现360度,所以使用下面的三目运算将360改为0
            azi2 = geodict1['azi2'] + 180 if geodict1['azi2'] != 180 else 0
            # 这句通过Q()函数实现 or 或逻辑,查询结果是源小区的经纬度是lnglat1且目标小区的经纬度是lnglat2的,
            # 或者源小区的经纬度是lnglat2且目标小区的经纬度是lnglat1的邻区对
            lnglat_set1 = queryset.filter(Q(cellfrom__lnglat=lnglat1) & Q(cellto__lnglat=lnglat2))
            lnglat_set2 = queryset.filter(Q(cellfrom__lnglat=lnglat2) & Q(cellto__lnglat=lnglat1))
            affectedrows = lnglat_set1.update(distance=round(geodict1['s12']), azi1=azi1, azi2=azi2)
            affectedrows += lnglat_set2.update(distance=round(geodict1['s12']), azi1=azi2, azi2=azi1)
            '''
    '''
                azi1=Case(
                    When(cellfrom__lnglat=lnglat1, then=azi1),
                    When(cellfrom__lnglat=lnglat2, then=azi2)
                ),
                azi2=Case(
                    When(cellto__lnglat=lnglat2, then=azi2),
                    # django.core.exceptions.FieldError: Joined field references are not permitted in this query
                    When(cellto__lnglat=lnglat1, then=azi1)
                ),
            )'''
    '''
            # 从邻区结果集中,去除这两个经纬度为起始和结束或结束和起始点的邻区对,剩余的结果集继续迭代到这个函数中。
            qset = queryset.exclude((Q(cellfrom__lnglat=lnglat1) & Q(cellto__lnglat=lnglat2)) |
                                    (Q(cellfrom__lnglat=lnglat2) & Q(cellto__lnglat=lnglat1)))
            # affectedrows += self.recursive(qset) 修改为如下形式为了将这个函数变为静态函数。
            affectedrows += Cellinforeader.recursive(qset)
            if affectedrows % 2000 < 20:
                print('已执行'+affectedrows+'行,当前时间'+datetime.datetime.now().strftime('%H:%M:%S'))
            return affectedrows
        else:
            return 0
    '''


class Checkpci:
    """检查pci冲突与混淆,得出可用pci"""

    # cgilist格式:['460-00-325632-129','460-00-325632-131'] D1 331 D1 332
    # freqpcilist格式:[{'cellname': 'Z737423嘉兴线务局LY建委大楼WZD_129', 'freq': 'D1', 'pci': 341},
    #                   {'cellname': 'Z730485嘉兴纺织大厦D_1', 'freq': 'D1', 'pci': 115}]
    # def __init__(self, cgilist=None, freqpcilist=None):
    def __init__(self, freqlist=None, mod3list=None):
        if not freqlist:
            freqlist = ['F1', 'F2', 'D1', 'D2', 'D3']
        if not mod3list:
            mod3list = [0, 1, 2]
        self.freqpcimatrix = dict()
        for f in freqlist:
            self.freqpcimatrix[f] = [i for i in range(504) if i % 3 in mod3list]
        # 用于存放邻区的邻区的pci频点小区名cgi
        self.adjdict = dict()

    # 根据输入的频点和PCI,从初始化freqpcimatrix频点PCI矩阵中剔除相应频点的PCI,参数格式("freq", "pci")
    def delfreqpci(self, freqpcilist=None):
        if freqpcilist:
            for freq, pci in freqpcilist:
                try:
                    self.freqpcimatrix.get(freq).remove(pci)
                except (AttributeError, ValueError) as e:
                    print(repr(e))
                    print('预置的频点PCI矩阵中没有' + freq + '频点,或PCI' + str(pci))

    # 根据输入的小区cgi列表,查询对应的小区频点和PCI,从初始化频点PCI矩阵中剔除
    def delbycgi(self, cgilist=None, cellnamelist=None):
        freqpcilist = None
        if cgilist:
            try:
                freqpcilist = ZJcell.objects.filter(cgi__in=cgilist).values_list("freq", "pci")
            except TypeError as e:
                print(repr(e))
                print('cgilist参数为空,或者格式不对')
        elif cellnamelist:
            try:
                freqpcilist = ZJcell.objects.filter(cellname__in=cellnamelist).values_list("freq", "pci")
            except TypeError as e:
                print(repr(e))
                print('cellnamelist参数为空,或者格式不对')
        if freqpcilist:
            self.delfreqpci(freqpcilist=freqpcilist)

    # 根据输入的小区,查找该小区邻区表,将这个小区及其邻区的频点PCI从列表中剔除。
    def delbycelladj(self, cgi=None, cellname=None):
        source = None
        freqpcilist = []
        if cgi:
            try:
                source = ZJcell.objects.get(cgi__exact=cgi)
            except (ZJcell.DoesNotExist, MultipleObjectsReturned) as e:
                print(repr(e))
                print('邻区表中的源小区cgi在小区表中不存在......:' + cgi)
        elif cellname:
            try:
                source = ZJcell.objects.get(cellname__exact=cellname)
            except (ZJcell.DoesNotExist, MultipleObjectsReturned) as e:
                print(repr(e))
                print('邻区表中的源小区cgi在小区表中不存在......:' + cgi)
        if source:
            freqpcilist = [(source.freq, source.pci)]
            # 增加.distinct()去重
            adjfreqpcilist = source.adj.values_list('freq', 'pci').distinct()
            # 增加邻区的邻区列表,已方便人工核查
            self.adjdict[source.cellname] = list(source.adj.values(邻区的邻区=F('cellname'), 邻邻区的cgi=F('cgi'),
                                                                   频点=F('freq'), 邻邻区的pci=F('pci')))
            # extend方法是list[]特有的,'QuerySet' object has no attribute 'extend'
            freqpcilist.extend(adjfreqpcilist)
            # freqpcilist在扩展(extend)后仍是list类型,不会变为QuerySet
        if freqpcilist:
            # 直接调用根据频点PCI列表删除预设表中的频点PCI项的函数delfreqpci,与上个函数delbycgi是平行的。
            self.delfreqpci(freqpcilist=freqpcilist)

    # 输入指定的邻小区列表,将这些邻区的邻区中存在的频点和pci组合从初始频点PCI矩阵中剔除。
    # 注意,这个函数与delbycgi()区别是,这个函数还需要查找列表中的小区的邻区,而delbycgi()只查列表中的小区。
    def delbycelllist(self, readfrom=r'C:\Users\Administrator\Desktop\嘉兴工参\邻区cgi.xlsx', sheet_name='Sheet1',
                      cgilist=None, cellnamelist=None):
        if cgilist:
            for cgi in cgilist:
                self.delbycelladj(cgi=cgi)
        elif cellnamelist:
            for cellname in cellnamelist:
                self.delbycelladj(cellname=cellname)
        elif readfrom:
            # header=None 表示没有列投,从第一行开始就是数据
            dfcgi = pd.read_excel(readfrom, sheet_name=sheet_name, header=None)
            # .stack()函数作用:转置,列传行,其实stack作用比转置大,.T才是转置
            nparr = np.array(dfcgi.stack())
            # .tolist()将np数组转为list数组[]
            cgiarray = nparr.tolist()
            for cgi in cgiarray:
                self.delbycelladj(cgi=cgi)
                # print(cgi)

    def outputpci(self, path=r'J:\pci列表.xlsx'):
        df1 = pd.DataFrame(self.freqpcimatrix)
        # df.to_excel(path)
        # 建立空df表
        df2 = pd.DataFrame()
        with pd.ExcelWriter(path) as writer:
            df1.to_excel(writer, sheet_name='未使用PCI')
            # 循环遍历邻区的邻区字典中的每个邻区列表,输出到excel
            for source in self.adjdict:
                # 利用字典创建df表
                df_tmp = pd.DataFrame(self.adjdict[source])
                # 在df表的0列插入一列源小区名
                df_tmp.insert(0, '规划小区的邻区', source)
                # 将某一个源小区的邻区df表,合并到整个邻区表的后面
                df2 = df2.append(df_tmp, ignore_index=True)
            # 输出整个邻区表到另一个sheet
            df2.to_excel(writer, sheet_name='规划小区的邻区的邻区列表')


# 根据经纬度及搜索范围,查找pci的最小复用距离,即pci列表中每个pci在所给经纬度点处,计算距离最近的同频同pci小区的距离
class Findsamepci:
    """以经纬度点为圆心,查找搜索半径内,与所给pci列表中相同PCI的小区,并计算小区到圆心距离,这个距离成为最小复用距离"""

    # 初始化函数的作用是确定圆心及半径,并找出半径内所有小区。注意,因为只找小区,不找小区的邻区,为了尽可能多的找到
    # 全部复用的PCI,所以半径必须足够大,一般应超过10公里(km),这样才能从更广的范围内查找最小复用距离。
    def __init__(self, lng, lat, radius=20000):
        self.lng = lng
        self.lat = lat
        self.radius = radius
        north = Geodesic.WGS84.Direct(lat, lng, 0, radius)
        northlat = north['lat2']
        south = Geodesic.WGS84.Direct(lat, lng, 180, radius)
        southlat = south['lat2']
        east = Geodesic.WGS84.Direct(lat, lng, 90, radius)
        # 由于复制上面的'lat2'没有改成'lon2',导致查询结果为空。
        eastlng = east['lon2']
        west = Geodesic.WGS84.Direct(lat, lng, 270, radius)
        westlng = west['lon2']
        self.cellinrectangle_list = ZJcell.objects.filter(lnglat__lng__gt=westlng, lnglat__lng__lt=eastlng,
                                                          lnglat__lat__gt=southlat, lnglat__lat__lt=northlat)
        # 经过测试,这样用相当于建立了两个不同的QuerySet对象:
        '''
        source_list = ZJcell.objects.filter(cgi__in=['460-00-325632-129','460-00-325632-131'])
        another_list=source_list
        another_list
        <QuerySet [<ZJcell: Z736934嘉兴质检所D_129>, <ZJcell: Z736934嘉兴质检所D_131>]>
        source_list
        <QuerySet [<ZJcell: Z736934嘉兴质检所D_129>, <ZJcell: Z736934嘉兴质检所D_131>]>
        another_list = source_list.exclude(cgi__exact='460-00-325632-129')
        another_list
        <QuerySet [<ZJcell: Z736934嘉兴质检所D_131>]>
        source_list
        <QuerySet [<ZJcell: Z736934嘉兴质检所D_129>, <ZJcell: Z736934嘉兴质检所D_131>]>
        '''
        # 不用提前将矩形区域转成圆形区域。到测距时,在判断是否超范围。
        # self.cellincycle_list = cellinrectangle_list
        # 存放频点-》PCI-》小区列表结构的dict,方便查找
        # self.freqpcicell_dict = None
        # 存放区域内已存在的频点和PCI
        self.existed_freqpci_matrix = dict()
        if self.cellinrectangle_list:
            # freqpci_list = cellinrectangle_list.values('freq', 'pci').distinct().annotate(num=Count('id'))
            # 通过聚合化区域内所有站点的频点,得到这些基站的频点分类,如D1,F1,利用频点分类作为数据字典的key
            freq_list = self.cellinrectangle_list.values('freq').distinct()
            # freq_list格式<QuerySet [{'freq': 'D1'}]>
            for freq in freq_list:
                # freqstr作为数据字典的key和过滤函数的查询条件
                freqk = freq['freq']
                # 通过每个频点,过滤后,列出所有不重复的pci,用于生成该频点的pci列表。
                pci_list = self.cellinrectangle_list.filter(freq__exact=freqk).values('pci').order_by('pci').distinct()

                # 下面的矩阵的格式:{'D1': [0, 1, 2, 3, ..., 503], 'F1': [0, 1, 2, 3, ..., 503], ...}
                self.existed_freqpci_matrix[freqk] = [pci['pci'] for pci in pci_list]

    # 查单个频点PCI在圆点处的最小复用距离
    def samepcidistance(self, freq, pci):
        specified_pci_cell_list = self.cellinrectangle_list.filter(freq__exact=freq, pci__exact=pci)
        distance = self.radius * 2
        cgi = None
        cellname = None
        if specified_pci_cell_list:
            for cell in specified_pci_cell_list:
                geodict1 = Geodesic.WGS84.Inverse(self.lat, self.lng, cell.lnglat.lat, cell.lnglat.lng)
                if distance > geodict1['s12']:
                    distance = geodict1['s12']
                    cgi = cell.cgi
                    cellname = cell.cellname
        if distance > self.radius:
            distance = self.radius
        return {'cellname': cellname, 'cgi': cgi, 'distance': round(distance)}

    # 查频点和PCI字典中,每个频点PCI组合在圆心处的最小复用距离。
    # 格式{'F1': {'1': {'cellname': 'Z736934嘉兴质检所D_129', 'cgi': '460-00-325632-129', 'distance': 20000},
    #             '2': {}...}
    #      'D1':{}}
    #
    def freqpcilistdistances(self, freqpcimatrix=None, saveto=r'J:/pci最小复用距离.xlsx'):
        if freqpcimatrix is None:
            freqpcimatrix = self.existed_freqpci_matrix
        # minpcidistance = {}
        minpcidistance = dict()
        column_name = ['cellname', 'cgi', 'freq', 'pci', 'distance']
        df = pd.DataFrame([], columns=column_name)
        for freq in freqpcimatrix:
            # minpcidistance = {'F1':{}}
            minpcidistance[freq] = {}
            pcilist = freqpcimatrix[freq]
            for pci in pcilist:
                mindistance = self.samepcidistance(freq, pci)
                # minpcidistance = {'F1':{'1':{samepcidistance函数的返回值}}}
                minpcidistance[freq][str(pci)] = mindistance
                data1 = [[mindistance['cellname'], mindistance['cgi'], freq, pci, mindistance['distance']]]
                df1 = pd.DataFrame(data1, columns=column_name)
                df = df.append(df1, ignore_index=True)
        df.to_excel(saveto)
        return minpcidistance

猜你喜欢

转载自blog.csdn.net/qq_27361945/article/details/83580923
PCI