from pymongo import MongoClient

# Criação do banco de dados com mongoimport
# docker cp books.json mongodb:/tmp/books.json
# cd tmp
# mongoimport --db library --collection books (continua)
#  --drop --file books.json --jsonArray

category = input("Escolha uma categoria: ")
with MongoClient() as client:
    db = client.library
    books = db.books.find({"categories": category})
    for book in books:
        print(book["title"])


from opentrons import protocol_api
from opentrons import types
from opentrons.protocol_api.labware import Well
import math
from types import MethodType
import subprocess
from opentrons.protocols.api_support.types import APIVersion

metadata = {
    'protocolName': 'Omega Bio-Tek Mag-Bind Plant DNA DS Kit',
    'author': 'Opentrons <protocols@opentrons.com>',
    'source': 'Custom Protocol Request',
    'apiLevel': '2.13'
}

AUDIO_FILE_PATH = '/etc/audio/speaker-test.mp3'

def run_quiet_process(command):
    subprocess.check_output('{} &> /dev/null'.format(command), shell=True)

def test_speaker(song=AUDIO_FILE_PATH):
    print('Speaker')
    print('Next\t--> CTRL-C')
    try:
        run_quiet_process('mpg123 {}'.format(song))
    except KeyboardInterrupt:
        pass
        print()

def run(ctx: protocol_api.ProtocolContext):
    [
     _m300_mount,
     _num_samps,
     _inc_time,
     _mag_time,
     _air_dry,
     _add_water,
     _samp_labware,
     _asp_ht,
     _fin_wash,
     _elution_vol,
     _off_deck,
     _music
    ] = get_values(  # noqa: F821 (<--- DO NOT REMOVE!)
         '_m300_mount',
         '_num_samps',
         '_inc_time',
         '_mag_time',
         '_air_dry',
         '_add_water',
         '_samp_labware',
         '_asp_ht',
         '_fin_wash',
         '_elution_vol',
         '_off_deck',
         '_music')

    if not 1 <= _num_samps <= 96:
        raise Exception('The Number of Samples should be between 1 and 96')

    # define all custom variables above here with descriptions

    m300_mount = _m300_mount  # mount for 8-channel p300 pipette
    num_cols = math.ceil(_num_samps/8)  # number of sample columns
    samp_labware = _samp_labware  # labware containing sample
    elution_vol = _elution_vol  # volume of elution buffer
    inc_time = _inc_time  # time for binding step
    mag_time = _mag_time  # time on magnetic module
    air_dry = _air_dry  # time for air drying
    fin_wash = _fin_wash  # volume for final wash removal
    asp_ht = _asp_ht  # height from the top of the labware to aspirate from
    add_water = _add_water  # True/False for adding water prior to air dry
    off_deck = _off_deck  # True/False perform resuspension off-deck
    music = _music  # play custom music (only in Oregon)

    mag_deck = ctx.load_module('magnetic module gen2', 7)

    # load labware
    rsvr_12 = [ctx.load_labware('nest_12_reservoir_15ml', s) for s in [2, 3]]
    rsvr_1 = ctx.load_labware('nest_1_reservoir_195ml', 10)
    pcr_plate = ctx.load_labware('nest_96_wellplate_100ul_pcr_full_skirt', 1)
    samp_plate = ctx.load_labware(samp_labware, 4)
    mag_plate = mag_deck.load_labware('nest_96_wellplate_2ml_deep')

    # load tipracks
    tips = [
        ctx.load_labware(
            'opentrons_96_filtertiprack_200ul', s) for s in [5, 6, 8, 9, 11]
            ]
    all_tips = [t for rack in tips for t in rack.rows()[0]]
    t_start = 0
    t_end = int(num_cols)

    # load instrument
    m300 = ctx.load_instrument('p300_multi_gen2', m300_mount, tip_racks=tips)

    # extend well objects for improved liquid handling
    class WellH(Well):
        def __init__(self, well, min_height=0.5, comp_coeff=1.1,
                     current_volume=0):
            super().__init__(well.parent, well._core, APIVersion(2, 13))
            self.well = well
            # specified minimum well bottom clearance
            self.min_height = min_height
            self.comp_coeff = comp_coeff
            # specified starting volume in ul
            self.current_volume = current_volume
            # cross sectional area
            if self.diameter is not None:
                self.radius = self.diameter/2
                cse = math.pi*(self.radius**2)
            elif self.length is not None:
                cse = self.length*self.width
            else:
                cse = None
            self.cse = cse
            # initial liquid level in mm from start vol
            if cse:
                self.height = (current_volume/cse)
            else:
                raise Exception('Labware definition must \
supply well radius or well length and width.')
            if self.height < min_height:
                self.height = min_height
            elif self.height > well.parent.highest_z:
                raise Exception('Specified liquid volume \
can not exceed the height of the labware.')

        def height_dec(self, vol, ppt, bottom=False):
            # decrement height (mm)
            dh = (vol/self.cse)*self.comp_coeff
            # tip immersion (mm) as fraction of tip length
            mm_immersed = 0.05*ppt._tip_racks[0].wells()[0].depth
            # decrement til target reaches specified min clearance
            self.height = self.height - dh if (
             (self.height - dh - mm_immersed) > self.min_height
             ) else self.min_height + mm_immersed
            self.current_volume = self.current_volume - vol if (
             self.current_volume - vol > 0) else 0
            tip_ht = self.height - mm_immersed if bottom is False else bottom
            return self.well.bottom(tip_ht)

        def height_inc(self, vol, top=False):
            # increment height (mm)
            ih = (vol/self.cse)*self.comp_coeff
            # keep calculated liquid ht between min clearance and well depth
            self.height = self.min_height if (
             self.height < self.min_height) else self.height
            self.height = (self.height + ih) if (
             (self.height + ih) < self.depth) else self.depth
            # increment
            self.current_volume += vol
            if top is False:
                tip_ht = self.height
                return self.well.bottom(tip_ht)
            else:
                return self.well.top()

    # pipette functions   # INCLUDE ANY BINDING TO CLASS
    def aspirate_h(self, vol, source, rate=1, bottom=False):
        self.aspirate(
         vol, source.height_dec(vol, self, bottom=bottom), rate=rate)

    def dispense_h(self, vol, dest, rate=1, top=False):
        self.dispense(vol, dest.height_inc(vol, top=top), rate=rate)

    def slow_tip_withdrawal(
     self, speed_limit, well_location, to_surface=False):
        if self.mount == 'right':
            axis = 'A'
        else:
            axis = 'Z'
        previous_limit = None
        if axis in ctx.max_speeds.keys():
            for key, value in ctx.max_speeds.items():
                if key == axis:
                    previous_limit = value
        ctx.max_speeds[axis] = speed_limit
        if to_surface is False:
            self.move_to(well_location.top())
        else:
            if isinstance(well_location, WellH):
                self.move_to(well_location.bottom().move(types.Point(
                 x=0, y=0, z=well_location.height+(
                  20*(self._tip_racks[0].wells()[0].depth / 88)))))
            else:
                self.move_to(well_location.center())
        ctx.max_speeds[axis] = previous_limit

    def custom_pick_up(self, loc=None):
        nonlocal t_start
        nonlocal t_end
        # `custom_pick_up` will pause the protocol when all tip boxes are out
        # of tips, prompting the user to replace all tip racks. Once tipracks
        # reset, the protocol will start picking up tips from the first tip
        # box as defined in the slot order when assigning the labware def
        # for that tip box. `pick_up()` will track tips for both pipettes if
        # applicable.

        # :param loc: User can manually specify location for tip pick up

        if loc:
            self.pick_up_tip(loc)
        else:
            try:
                self.pick_up_tip()
            except protocol_api.labware.OutOfTipsError:
                flash_lights()
                ctx.pause('Replace empty tip racks')
                self.reset_tipracks()
                t_start = 0
                t_end = int(num_cols)
                ctx.set_rail_lights(True)
                self.pick_up_tip()

    # bind additional methods to pipettes
    for met in [aspirate_h, dispense_h, slow_tip_withdrawal, custom_pick_up]:
        setattr(
         m300, met.__name__,
         MethodType(met, m300))

    # reagents
    liquid_waste = rsvr_1.wells()[0].top()
    # cspl = [WellH(well) for well in rsvr_12[0].wells()[:6]]
    # for idx in range(num_cols):
    #     cspl[idx//2].height_inc(720*8*1.1)

    # helper functions
    def flash_lights():
        for _ in range(19):
            ctx.set_rail_lights(not ctx.rail_lights_on)
            ctx.delay(seconds=0.25)

    def flow_rate(asp=92.86, disp=92.86, blow=92.86):
        # This function can be used to quickly modify the flow rates of the
        # m300. If no parameters are entered, the flow rates will be
        # reset.

        # :param asp: Aspiration flow rate, in uL/sec
        # :param disp: Dispense flow rate, in uL/sec

        m300.flow_rate.aspirate = asp
        m300.flow_rate.dispense = disp
        m300.flow_rate.blow_out = blow

    def remove_supernatant(vol, src):
        w = int(str(src).split(' ')[0][1:])
        if src.width is not None:
            radi = float(src.width)/4
        else:
            radi = float(src.diameter)/4
        x0 = radi if w % 2 == 0 else -radi
        while vol > 180:
            m300.aspirate(180, src.bottom().move(types.Point(x=x0, y=0, z=1)))
            m300.dispense(200, liquid_waste)
            m300.blow_out()
            m300.aspirate(20, liquid_waste)
            vol -= 180
        m300.aspirate(vol, src.bottom().move(types.Point(x=x0, y=0, z=0.7)))
        m300.dispense(vol+20, liquid_waste)
        m300.blow_out()
        m300.aspirate(10, liquid_waste)

    def wash(srcs, msg, sup=600):
        nonlocal t_start
        nonlocal t_end

        if mag_deck.status == 'engaged':
            mag_deck.disengage()
        ctx.comment(f'Performing wash step: {msg}')
        flow_rate()
        for idx, (col, src) in enumerate(zip(mag_samps_h, srcs)):
            m300.custom_pick_up()
            # src = srcs[idx//3]
            for i in range(2):
                flow_rate(asp=150, disp=150)
                if i == 1:
                    m300.dispense(20, src.top(-1))
                    m300.dispense(20, src)
                m300.mix(1, 200, src)
                flow_rate()
                m300.aspirate(200, src)
                m300.slow_tip_withdrawal(10, src, to_surface=True)
                m300.dispense(180, col.top(-2))
                flow_rate(asp=10)
                m300.aspirate(20, col.top())
            m300.dispense(20, src.top())
            flow_rate()
            m300.mix(1, 140, src)
            m300.aspirate(140, src)
            m300.slow_tip_withdrawal(10, src, to_surface=True)
            m300.dispense(140, col)
            if not off_deck:
                m300.mix(10, 100, col)
            ctx.delay(seconds=5)
            m300.slow_tip_withdrawal(10, col, to_surface=True)
            m300.blow_out()
            m300.touch_tip(speed=40)
            m300.aspirate(10, col.top())
            m300.drop_tip()

        if off_deck:
            flash_lights()
            ctx.pause('Please remove plate for manual resuspension')

        mag_deck.engage()
        mag_msg = f'Incubating on Mag Deck for {mag_time} minutes'
        ctx.delay(minutes=mag_time, msg=mag_msg)

        # Discard Supernatant
        ctx.comment(f'Removing supernatant for wash: {msg}')
        t_start += num_cols
        t_end += num_cols
        for src, t_d in zip(mag_samps_h, all_tips[t_start:t_end]):
            m300.custom_pick_up()
            remove_supernatant(sup, src)
            m300.drop_tip(t_d)

    # plate, tube rack maps
    init_samps = samp_plate.rows()[0][:num_cols]
    mag_samps = mag_plate.rows()[0][:num_cols]
    mag_samps_h = [WellH(well) for well in mag_samps]
    pcr_samps = pcr_plate.rows()[0][:num_cols]

    # protocol
    ctx.set_rail_lights(True)
    # # Transfer 700µL CSPL Buffer + 20µL Prot K
    # ctx.comment('Transferring 720uL of CSPL Buffer + Proteinase K')
    #
    # m300.custom_pick_up()
    # for idx, col in enumerate(init_samps):
    #     src = cspl[idx//2]
    #     for _ in range(4):
    #         m300.aspirate_h(180, src)
    #         m300.slow_tip_withdrawal(10, src, to_surface=True)
    #         m300.dispense(180, col.top(-2))
    # m300.drop_tip()
    #
    # flash_lights()
    # ctx.pause('Please remove samples and incubate at 56C for 30 minutes, \
    # then centrifuge at 4000g for 10 minutes. Once complete, please replace \
    # samples on the deck and place ensure 12-well reservoirs are filled with \
    # necessary reagents in deck slots 2 and 3. When ready, click RESUME.')
    # ctx.set_rail_lights(True)
    # Creating reagent variables for second part of protocol
    rbb = [WellH(well, current_volume=0) for well in rsvr_12[0].wells()[:4]]
    cspw1 = [WellH(well) for well in rsvr_12[0].wells()[4:8]]
    cspw2 = [WellH(well) for well in rsvr_12[0].wells()[8:]]
    spm = [WellH(well) for well in rsvr_12[1].wells()[:8]]
    h2o = rsvr_12[1]['A9']
    elution_buffer = [WellH(well) for well in rsvr_12[1].wells()[10:]]

    cspw1_wells = []
    cspw2_wells = []
    spm1_wells = []
    spm2_wells = []
    elution_wells = []

    for idx in range(num_cols):
        rbb[idx//3].height_inc(525*8)
        cspw1[idx//3].height_inc(500*8)
        cspw2[idx//3].height_inc(500*8)
        elution_buffer[idx//6].height_inc(elution_vol*8)
        cspw1_wells.append(cspw1[idx//3])
        cspw2_wells.append(cspw2[idx//3])
        elution_wells.append(elution_buffer[idx//6])

    for idx in range(num_cols*2):
        spm[idx//3].height_inc(500*8)
        if idx % 2 == 0:
            spm1_wells.append(spm[idx//3])
        else:
            spm2_wells.append(spm[idx//3])

    reagent_keys = {
        'RBB + RNase + Mag-Bind Beads': rbb,
        'CSPW 1 Buffer': cspw1,
        'CSPW 2 Buffer': cspw2,
        'Elution Buffer': elution_buffer,
        'SPM': spm,
    }
    for key in reagent_keys:
        for x in reagent_keys[key]:
            ctx.comment(f'load {x.current_volume} of {key} in {x}')
    # for x in rbb:
    #     ctx.comment(f'load {x.current_volume} in {x}')

    if samp_labware == 'qiagen_96_tuberack_1200ul':
        ctx.comment('Transferring 500uL of sample to plate on MagDeck')

        flow_rate(asp=20)
        for src, dest in zip(init_samps, mag_samps_h):
            src_asp = src.top(-asp_ht)
            m300.custom_pick_up()
            for i in range(2):
                m300.aspirate(20, src.top())
                m300.aspirate(180, src_asp)
                m300.slow_tip_withdrawal(10, src)
                m300.dispense_h(180, dest)
                m300.slow_tip_withdrawal(10, dest, to_surface=True)
                m300.dispense(20, dest.bottom(5))
            m300.aspirate(20, src.top())
            m300.aspirate(140, src_asp)
            m300.dispense_h(140, dest)
            m300.slow_tip_withdrawal(10, dest, to_surface=True)
            m300.dispense(20, dest.bottom(5))
            m300.drop_tip()
        flow_rate()
    else:
        flash_lights()
        ctx.pause('Please make sure samples are loaded on MagDeck')

    # Transfer 5uL RNAse + 500uL RBB buffer + 20uL Mag-Bind Beads
    ctx.comment('Transferring 5uL RNAse + 500uL RBB buffer + \
20uL Mag-Bind Beads')

    m300.custom_pick_up()
    flow_rate(blow=10)
    for idx, dest in enumerate(mag_samps):
        src = rbb[idx//3]
        for _ in range(3):
            flow_rate(asp=20, disp=20)
            m300.mix(1, 100, src)
            m300.aspirate(175, src)
            m300.slow_tip_withdrawal(10, src, to_surface=True)
            flow_rate(disp=10)
            m300.dispense(75, dest.top(-1))
            flow_rate(disp=5)
            m300.dispense(50, dest.top(-1))
            ctx.delay(seconds=3)
            m300.dispense(30, dest.top(-1))
            ctx.delay(seconds=3)
            flow_rate(disp=2)
            m300.dispense(20, dest.top(-1))
            m300.blow_out()
            m300.touch_tip(speed=40)
    m300.drop_tip()
    flow_rate()

    if off_deck:
        flash_lights()
        ctx.pause('Please incubate samples for 10 minutes post resuspension.')
    else:
        incubate_msg = f'Incubating at room temperature for {inc_time} \
minutes plus mixing'
        ctx.comment(incubate_msg)

        if num_cols > 1:
            num_mixes = math.ceil(2*inc_time/num_cols)
        else:
            num_mixes = 10
        for _ in range(num_mixes):
            for col, t_d in zip(mag_samps, all_tips[t_start:t_end]):
                if _ == 0:
                    m300.custom_pick_up()
                if not m300.has_tip:
                    m300.custom_pick_up(t_d)
                m300.mix(8, 150, col)
                ctx.delay(seconds=1)
                m300.blow_out(col.top(-2))
                m300.touch_tip()
                if len(mag_samps) > 1:
                    m300.drop_tip(t_d)
                else:
                    ctx.delay(seconds=30)
        if m300.has_tip:
            m300.drop_tip(t_d)

        t_start += num_cols
        t_end += num_cols
    mag_deck.engage()
    mag_msg = f'Incubating on Mag Deck for {mag_time} minutes'
    ctx.delay(minutes=mag_time, msg=mag_msg)

    # Discard Supernatant
    ctx.comment('Removing supernatant')
    flow_rate(asp=40, disp=40)
    for src, t_d in zip(mag_samps_h, all_tips[t_start:t_end]):
        m300.custom_pick_up()
        remove_supernatant(540, src)
        m300.drop_tip()
        m300.custom_pick_up()
        remove_supernatant(540, src)
        m300.drop_tip(t_d)

    flow_rate()

    # Wash with 500uL CSPW1 Buffer
    wash(cspw1_wells, 'CSPW1')

    # Wash with 500uL CSPW2 Buffer
    wash(cspw2_wells, 'CSPW2')

    # Wash with SPM Buffer (1)
    wash(spm1_wells, 'SPM (first wash)')

    # Wash with SPM Buffer (2)
    wash(spm2_wells, 'SPM (second wash)', fin_wash)

    # Air dry for 10 minutes
    mag_deck.engage()
    if add_water:
        for src in mag_samps_h:
            m300.custom_pick_up()
            m300.aspirate(100, h2o)
            flow_rate(asp=30, disp=30)
            m300.dispense(80, src)
            ctx.delay(seconds=0.5)
            m300.aspirate(100, src)
            flow_rate()
            m300.dispense(120, liquid_waste)
            m300.blow_out()
            m300.drop_tip()

    ctx.home()
    air_dry_msg = f'Air drying the beads for {air_dry} minutes. \
Please add elution buffer at 65C to 12-well reservoir.'
    ctx.delay(minutes=air_dry, msg=air_dry_msg)
    flash_lights()
    if not ctx.is_simulating():
        if music:
            test_speaker('/var/lib/jupyter/notebooks/mr-blue-sky-ot2.mp3')
        else:
            test_speaker()
    ctx.pause('Please check the Well Plate')

    mag_deck.disengage()
    # Add Elution Buffer
    ctx.comment(f'Adding {elution_vol}uL Elution Buffer to samples')

    for idx, (col, src) in enumerate(zip(mag_samps_h, elution_wells)):
        m300.custom_pick_up()
        m300.aspirate(elution_vol, src)
        m300.slow_tip_withdrawal(10, src, to_surface=True)
        m300.dispense_h(elution_vol, col)
        if not off_deck:
            m300.mix(10, 50, col)
        m300.slow_tip_withdrawal(10, col, to_surface=True)
        m300.blow_out(col.bottom(6))
        for _ in range(2):
            m300.move_to(col.bottom(5))
            m300.move_to(col.bottom(6))
        m300.drop_tip()

    flash_lights()
    ctx.home()
    if not ctx.is_simulating():
        if music:
            test_speaker('/var/lib/jupyter/notebooks/all-i-want-ot2.mp3')
        else:
            test_speaker()
    ctx.pause('Please remove samples and incubate at 65C for 5 minutes.\
When complete, replace samples and click RESUME')
    ctx.set_rail_lights(True)

    # Transfer elution to PCR plate
    if not off_deck:
        for col in mag_samps_h:
            m300.custom_pick_up()
            m300.mix(10, 50, col)
            m300.slow_tip_withdrawal(10, col, to_surface=True)
            m300.blow_out(col.bottom(6))
            for _ in range(2):
                m300.move_to(col.bottom(5))
                m300.move_to(col.bottom(6))
            m300.drop_tip(home_after=False)
    else:
        ctx.comment('Please perform manual resupsension off deck.')

    mag_deck.engage()
    mag_msg = 'Incubating on Mag Deck for 3 minutes'
    ctx.delay(minutes=3, msg=mag_msg)

    ctx.comment(f'Transferring {elution_vol}uL to final PCR plate')
    t_start += num_cols
    if t_start >= 60:
        t_start -= 60

    flow_rate(asp=20)
    for src, dest, tip in zip(mag_samps, pcr_samps, all_tips[t_start:]):
        w = int(str(src).split(' ')[0][1:])
        if src.width is not None:
            radi = float(src.width)/4
        else:
            radi = float(src.diameter)/4
        x0 = radi if w % 2 == 0 else -radi
        m300.custom_pick_up()
        m300.aspirate(
            elution_vol, src.bottom().move(types.Point(x=x0, y=0, z=1)))
        m300.dispense(elution_vol, dest)
        m300.drop_tip(tip)

    mag_deck.disengage()
    ctx.comment('Protocol complete! Please store samples at -20C or \
continue processing')


import sublime  # To obtain plugin settings
import logging

# Define the plugin logger, to be initialized on `plugin_loaded()`
logger = logging.getLogger(__name__)

def InitializeMainLogger():
    """ Apply required settings to the main RTags logger.
    """
    # Remove all previously added handlers, if any (relevant when reloading)
    logger.handlers = []

    # Must be set to lowest level to get total freedom in handlers
    logger.setLevel(logging.DEBUG)

    # Disable log duplications when reloading
    logger.propagate = False

    # Create console handler with the requested logging level
    console_handler = logging.StreamHandler()
    logging_level = GetRequestedLoggingLevel()
    console_handler.setLevel(logging_level)

    # Create formatter and add it to the handler
    formatter = logging.Formatter('[RTags / %(levelname)s] %(message)s')
    console_handler.setFormatter(formatter)

    # Add the handler to logger
    logger.addHandler(console_handler)

def GetRequestedLoggingLevel():
    """ Returns the appropriate logging level value by the plugin settings.
    """
    rtags_settings = sublime.load_settings("RTags.sublime-settings")
    verbose_logging = rtags_settings.get("verbose")
    return logging.DEBUG if verbose_logging else logging.WARNING

def ReinitializeMainLogger():
    """ Reinitializes the plugin's logger in case the settings have changed.
    """
    if logger.handlers[0].level != GetRequestedLoggingLevel():
        InitializeMainLogger()


"""
爬取大学的课程数据
需在get_schools.py之后执行
"""

import multiprocessing
import requests
import logging
import json
from os import makedirs
from os.path import exists

# 日志输出格式
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')
# url
BASE_URL = 'https://www.icourse163.org'  # mooc主页
COURSE_URL = 'https://www.icourse163.org/web/j/courseBean.getCourseListBySchoolId.rpc?csrfKey={csrfkey}'  # ajax请求url,获取大学课程
# 保存目录
RESULTS_DIR = 'mooc_results/courses'
exists(RESULTS_DIR) or makedirs(RESULTS_DIR)

def get_csrf():
    """
    从cookie中获取csrf令牌，并返回它们
    :return:
    """
    csrf = ''
    r = requests.get(BASE_URL)
    for key, value in r.cookies.items():
        if key == 'NTESSTUDYSI':
            csrf = value
            logging.info('get csrf key')
    return r.cookies, csrf

def scrape_api(url, data, cookies):
    """
    以post方式请求url，返回json数据
    """
    # logging.info('scraping %s...', url)
    try:
        response = requests.post(url, data=data, cookies=cookies)
        if response.status_code == requests.codes.ok:  # 即200
            return response.json()
        logging.error('get invalid status code %s while scraping %s', response.status_code, url)
    except requests.RequestException:
        logging.error('error occurred while scraping %s', url, exc_info=True)

def scrape_courses(school_id, page, cookies, csrf):
    """
    传入大学id，以及页码，返回该页课程的json数据
    """
    url = COURSE_URL.format(csrfkey=csrf)
    data = {
        'schoolId': school_id,  # 学校id
        'p': page,  # 页码
        'psize': 20,  # 每页的课程数
        'type': 1,  # 不详
        'courseStatus': 30,  # 课程状态：全部（正在进行、即将开始、已结束）
    }
    result = scrape_api(url, data, cookies)
    logging.info('get courses of school id %s, page %s', school_id, page)
    return result

def get_params():
    """
    生成多进程需要的参数列表
    """
    # 定义参数列表
    params = []
    # 读取schools.json文件，得到全部学校名称和学校Id，存入参数列表
    with open('mooc_results/schools.json', 'r', encoding='utf-8') as file:
        schools = json.loads(file.read())
    for school in schools[:6]:
        params.append((school['school_name'], school['school_id']))
    return params

def save_data(data):
    """
    保存数据为json文件
    """
    # 获取学校名，将斜杠替换，防止路径歧义
    school_name = data.get('school_name').replace('/', '／').replace('\\', '＼')
    # 构建保存路径
    data_path = f'{RESULTS_DIR}/courses_of_{school_name}.json'
    exists(f'{RESULTS_DIR}') or makedirs(f'{RESULTS_DIR}')
    # 保存为json文件
    json.dump(data, open(data_path, 'w', encoding='utf-8'), ensure_ascii=False, indent=2)

    logging.info(f'saved {data_path}')

def main(school_name, school_id):
    """
    爬取一所大学的全部课程，保存为json文件
    :param school_name:
    :param school_id:
    :return:
    """
    # 定义课程列表
    courses = []
    # 获取cookie和csrf令牌
    cookies, csrf = get_csrf()
    # 爬取第一页课程
    first_data = scrape_courses(school_id, 1, cookies, csrf)
    # 得到该大学总课程数和总课程页数
    totle_count = int(first_data['result']['query']['totleCount'])
    totle_page_count = int(first_data['result']['query']['totlePageCount'])
    # 将课程存入课程列表
    if totle_count != 0:
        # 将第一页课程存入课程列表
        for course in first_data['result']['list']:
            courses.append(course)
        # 爬取其余页的课程，并存入课程列表
        for i in range(2, totle_page_count + 1):
            data = scrape_courses(school_id, i, cookies, csrf)
            for course in data['result']['list']:
                courses.append(course)
    # 保存为json文件
    school_courses = {
        'school_name': school_name,
        'school_id': school_id,
        'courses_count': totle_count,
        'school_courses': courses
    }
    save_data(school_courses)

if __name__ == '__main__':
    # 生成参数列表
    params = get_params()
    # 打印进程数（即cpu核数）
    print("Number of processers: ", multiprocessing.cpu_count())
    # 多进程爬取
    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    # pool.map(main,)
    pool.starmap(main, params)  # 维持执行的进程总数为[计算机cpu核数]，当一个进程执行完毕后会添加新的进程进去
    pool.close()  # 执行完close后不会有新的进程加入到pool
    pool.join()  # 主进程阻塞，等待所有子进程的退出


'''Definition of tf.keras compatible Layers

The tdl Layer is compatible with tf.keras layers and supports
autoinitialization with tdl descriptors.
'''
import types
import functools
import collections
import tensorflow as tf
from . import common
from .common import (InputArgument, InputParameter, InputModel, InferenceInput,
                     InputModelInit,
                     Submodel, SubmodelWithArgs, SubmodelInit, ParameterInit,
                     OutputValue,
                     SimpleParameter,
                     Regularizer, OptionalProperty,
                     is_property_initialized,
                     nest
                     )
from .search import get_variables, is_trainable, SEARCHABLE_CLASSES

def _assert_known_kargs(layer, kwargs):
    '''Checks if the provided arguments have an initialization method.'''
    known = common._find_tdl_attrs(
        type(layer), AttrClass=(),
        AttrBaseClass=common.TDL_INIT_DESCRIPTORS)
    for kwarg in kwargs:
        if kwarg not in known:
            raise TypeError('Unknown keyword argument:', kwarg)

@common.add_autoinit_class
class Layer(tf.keras.layers.Layer):
    '''TDL Layer that is compatible with tf.keras specification.'''

    def _tdl_check_kwargs(self, kwargs):
        '''custom defined function to check arguments before initialization'''
        return

    @InputArgument
    def input_shape(self, value):
        if value is None:
            # raise ValueError('the value of attribute {}.input_shape must be '
            #                  'provided'.format(type(self).__name__))
            return None
        if isinstance(value, (tuple, list)):
            if all(isinstance(i, (int, None)) for i in value):
                value = tf.TensorShape(value)
        flat = nest.flatten(value)
        if not all(isinstance(i, tf.TensorShape) for i in flat):
            raise ValueError('input_shape should be a TensorShape or a nested'
                             'structure of TensorShapes.')
        return value

    @property
    def scope(self):
        '''Scope for the model, used to define all operations.'''
        if not hasattr(self.__tdl__, '_scope'):
            with tf.name_scope(self.name) as scope:
                self.__tdl__._scope = scope
        return self.__tdl__._scope

    def _get_unique_name(self, name):
        def is_absolute(name):
            return name[0] == '/' or name[-1] == '/'
        name = (name if name is not None
                else type(self).__name__)
        if is_absolute(name):
            self.__tdl__._scope = name
        else:
            with tf.name_scope(name) as scope:
                self.__tdl__._scope = scope
        return self.scope[:-1]

    def __init__(self, trainable=True, name=None, *args,  **kwargs):
        '''Base initialization of a Tdl operation.
        Arguments should be explicitly specified. The basic acguments are:
            name: name of the model/operation, used to create a scope,
                  if no name is provided, the function will look for
                  self._default_name
            parameters corresponding to the specific model
            submodels corresponding to the specific model.
        '''
        if args:
            raise TypeError('arguments for tdl layers must be explicitly '
                            'stated')
        # initialize TDL instance for the descriptors
        if not hasattr(self, '__tdl__'):
            setattr(self, '__tdl__', common.__TDL__(self))
        # initialize name and scope
        name = self._get_unique_name(name)
        super(Layer, self).__init__(trainable=trainable, name=name)

        # auto initialize using the tdl descriptors
        self._tdl_check_kwargs(kwargs)
        _assert_known_kargs(self, kwargs)
        assert common.get_context(self).given_attrs is None
        common.get_context(self).given_attrs = \
            set([key for key, value in kwargs.items()])

        with tf.name_scope(self.scope), common.DisableAutoinit(self):
            attrs_done = common._init_tdl_attrs(
                self, kwargs, '_input_args',
                (InputArgument, InputParameter, InputModel, InferenceInput,
                 InputModelInit))
            allowed_autoinit = attrs_done
            attrs_done = common._init_tdl_attrs(
                self, kwargs, '_parameters',
                (SimpleParameter, ParameterInit),
                allowed_autoinit=allowed_autoinit)
            allowed_autoinit = set.union(attrs_done, allowed_autoinit)
            attrs_done = common._init_tdl_attrs(
                self, kwargs, '_submodels',
                (Submodel, SubmodelWithArgs, SubmodelInit),
                allowed_autoinit=allowed_autoinit)
            allowed_autoinit = set.union(attrs_done, allowed_autoinit)
            attrs_done = common._init_tdl_attrs(
                self, kwargs, '_model_outputs', OutputValue,
                allowed_autoinit=allowed_autoinit)
            allowed_autoinit = set.union(attrs_done, allowed_autoinit)
            attrs_done = common._init_tdl_attrs(
                self, kwargs, '_optional', (Regularizer, OptionalProperty),
                allowed_autoinit=allowed_autoinit)
        common.assert_initialized(self, '__init__',
                                  self.__tdl__._model_outputs)
        common.get_context(self).initialized = True

        # Wrap call method to update variables when finished
        def update_vars_wrapper(call_fn):
            @functools.wraps(call_fn)
            def call(obj, *args, **kargs):
                output = call_fn(obj, *args, **kargs)
                obj._update_variables()
                return output
            return call
        self.call = types.MethodType(
            update_vars_wrapper(self.call.__func__), self)
        self.build = types.MethodType(
            update_vars_wrapper(self.build.__func__), self)

    def build(self, input_shape=None):
        if input_shape is not None:
            if not is_property_initialized(self, 'input_shape'):
                self.input_shape = input_shape
        common.build(self)
        self.built = True
        return self

    def add_weight(self, *args, **kwargs):
        '''add a weight to the layer. If only one argument is provided, it
        should be an instance of tf.Variable. Otherwise, the signature is
        the same as tf.keras.Layer add_weight.'''
        if len(args) == 1 and not kwargs:
            variable = args[0]
            if self.trainable and isinstance(variable, tf.Variable):
                self._trainable_weights.append(variable)
            elif isinstance(variable, tf.Variable):
                self._non_trainable_weights.append(variable)
            else:
                raise ValueError('weight must be a variable instance')
            return variable
        else:
            return super(Layer, self).add_weight(*args, **kwargs)

    def _update_variables(self):
        '''Update the variables and weights list by searching through the
        attributes with tdl descriptors
        '''
        attr_names = collections.deque(
            common._find_tdl_attrs(
                type(self), AttrClass=common.TDL_INIT_DESCRIPTORS))
        vars = set()
        for name in attr_names:
            if common.is_property_initialized(self, name):
                attr = getattr(self, name)
                if isinstance(attr, (list, tuple)):
                    for attr_i in attr:
                        if isinstance(attr_i, SEARCHABLE_CLASSES):
                            vars |= set(get_variables(attr_i))
                elif isinstance(attr, SEARCHABLE_CLASSES):
                    vars |= set(get_variables(attr))
        vars = vars - set.union(set(self.trainable_weights),
                                set(self.non_trainable_weights))
        self._trainable_weights.extend(
            [v for v in vars if is_trainable(v)])
        self._non_trainable_weights.extend(
            [v for v in vars if not is_trainable(v)])


import os
import numpy as np
import pickle
import matplotlib.pyplot as plt
import hdbscan
from tqdm import tqdm
from sklearn.cluster import DBSCAN
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import itertools
from random import sample

class ClusterEmbedding():
    def __init__(self, cluster_img_dir, embeddings_dir, cluster_algorithm,
                    cluster_dir, eps=0.5, min_samples=5, n_clusters=15, fps=30, sample_rate=3, dim=30):
        self.cluster_img_dir = cluster_img_dir
        self.embeddings_dir = embeddings_dir
        self.cluster_algorithm = cluster_algorithm
        self.cluster_dir = cluster_dir
        self.eps = eps
        self.min_samples= min_samples
        self.n_clusters = n_clusters
        self.fps = fps
        self.sample_rate = sample_rate
        self.dim = dim

    def cluster_helper(self, embeddings):
        labels = None
        if self.cluster_algorithm.upper() == "DBSCAN":
            cluster = DBSCAN(eps=self.eps, min_samples=self.min_samples, n_jobs=-1).fit(embeddings)
            labels = cluster.labels_
        if self.cluster_algorithm.upper() == "KMEANS":
            cluster = KMeans(n_clusters=self.n_clusters).fit(embeddings)
            labels = cluster.labels_
        if self.cluster_algorithm.upper() == "HDBSCAN":
            cluster = hdbscan.HDBSCAN(min_cluster_size=self.n_clusters)
            labels = cluster.fit_predict(embeddings)
        self.plottr(labels, embeddings)
        print(len(set(labels)))
        return labels

    def plottr(self, labels, embeddings):
        if not os.path.isdir(self.cluster_img_dir):
            os.mkdir(self.cluster_img_dir)

        embeddings_arr = np.vstack(embeddings)
        plt.scatter(embeddings[:, 0], embeddings[:, 1], c=labels, cmap="plasma")
        # plt.scatter(embeddings_arr[:, 0], embeddings_arr[:, 1], c=labels, cmap="plasma")
        plt.xlabel("Feature 1")
        plt.ylabel("Feature 2")
        plt.title("Unique Events")
        plt.savefig(os.path.join(self.cluster_img_dir, self.cluster_algorithm + ".png"))
        plt.show()

    def subsample(self, length, embed_dict):
        window = self.fps
        rate = self.fps//self.sample_rate
        samples = []
        for i in range(0, length, window):
            if i + window < length:
                value = [*range(i, i + window)]
                samples.append(sample(value, rate))
            else:
                value = [*range(i, length)]
                samples.append(value)
        samples = list(itertools.chain.from_iterable(samples))
        samples.sort()

        frame_keys = list(embed_dict.keys())
        frame_keys_ = [frame_keys[i] for i in samples]
        frame_values_ = [embed_dict[i] for i in frame_keys_]
        return frame_keys_, frame_values_

    def reduce_dim(self, frame_values_):
        frames_arr = np.vstack(frame_values_)
        reduced = PCA(n_components=self.dim).fit(frames_arr).transform(frames_arr)
        print(reduced[0])
        return reduced

    def cluster(self):
        if not os.path.isdir(self.cluster_dir):
            os.mkdir(self.cluster_dir)
        embeddings = []
        frame_names = []

        cluster_dict = {}

        # get embeddings
        embed_dict = pickle.load(open(os.path.join(self.embeddings_dir, "frame_embeddings.pkl"), 'rb'))

        sample_frames, sample_embeddings = self.subsample(len(embed_dict), embed_dict)
        reduced_embeddings = self.reduce_dim(sample_embeddings)

        labels = self.cluster_helper(reduced_embeddings)
        for i in tqdm(range(len(sample_frames)), desc="Mapping frames to clusters", ncols=100):
            cluster_dict[sample_frames[i]] = labels[i]

        with open(os.path.join(self.cluster_dir, "frame_to_cluster.pkl"), 'wb') as file:
            pickle.dump(cluster_dict, file)


import numpy as np
import seaborn as sns
from matplotlib import pyplot as plt
from matplotlib import animation
from parameters import *
import math

row = 800
column = 600
x_bias = -100
y_bias = -100

def social_cost(people_position, waypoint, personal_space_deviation):
    dist = np.linalg.norm(people_position - waypoint)
    if dist < SAFE_RADIUS:
        return 1
    return np.exp( -dist**2 / personal_space_deviation**2)

def interaction_cost(people_position, waypoint, gaze_direction ,gaze_deviation):
    vector = waypoint - people_position
    angle = math.atan2(vector[1],vector[0]) - gaze_direction
    return np.exp( -(angle**2)/(gaze_deviation**2))

def People_influence(People_List, time,x,y):
    total = 0.0
    waypoint = np.array([x,y])
    for people in People_List:
        people_position = np.array([people.recorded_position_x[time],people.recorded_position_y[time]])
        total+= social_cost(people_position, waypoint, people.personal_space_deviation)
        total+= interaction_cost(people_position, waypoint, people.orientation ,people.gaze_deviation)
    return total

def Robot_influence(robot, time,x,y):
    waypoint = np.array([x,y])
    robot_position = np.array([robot.state[time,0], robot.state[time,1]])
    dist = np.linalg.norm(robot_position - waypoint)
    if dist <2 :
        return 1
    else:
        return 0

def generate_heatmap(robot, People_List):
    heat= []
    time = min(len(robot.state), len(People_List[0].recorded_position_y))
    for index in range(time):
        heat.append(np.zeros(shape=(row,column)))
        for x in range(row):
            for y in range(column):
                # heat[-1][x,y] += Robot_influence(robot, index, x+x_bias,y+y_bias)
                heat[-1][x,y] += People_influence(People_List, index,x+x_bias,y+y_bias)
        xmax, xmin = heat[-1].max(), heat[-1].min()
        heat[-1] = (heat[-1] - xmin)/(xmax - xmin)
    return heat

def HeatMap_Animation(robot, People_List):
    heat = generate_heatmap(robot, People_List)
    fig = plt.figure()
    data = heat[0]
    sns.heatmap(data, xticklabels= False, yticklabels= False)
    def init():
        sns.heatmap(np.zeros((row, column)), xticklabels= False, yticklabels= False)
    def animate(i):
        # print (i)
        plt.clf()
        sns.heatmap(heat[i-1], xticklabels= False, yticklabels= False)

    ani = animation.FuncAnimation(fig, animate, init_func = init, repeat = False)
    ani.save('heatmapy.gif', writer='imagemagick', fps=30 )
    plt.show()


import numpy as np
import matplotlib.pyplot as plt
import open3d as o3d
## unit 1px=1mm
## the total height is 90mm
## so Z range from 0 to 90
##
pcl = o3d.geometry.PointCloud()

def parametric_circle(t,xc,yc,R):
    x = xc + R*np.cos(t)
    y = yc + R*np.sin(t)
    return x,y

def inv_parametric_circle(x,xc,R):
    t = np.arccos((x-xc)/R)
    return t

x_all=[]
y_all=[]
z_all=[]
N = 30 # control point in the curve
R_z = (3.5*np.sqrt(3)+1.5)/3.5*90 # radius
R=1.5/3.5*90
xc_z = -3.5*np.sqrt(3)/3.5*90 # center x

fig = plt.figure()
ax = fig.add_subplot(projection='3d')
for z in np.arange(0,89,1):
    theta=np.arctan2(z,-xc_z)
    R=R_z+10-R_z*np.cos(theta)
    xc = 0.0 # center x
    yc = 0.0 # center y
    start_point = (xc + R*np.cos(0), yc + R*np.sin(0))
    end_point   = (xc + R*np.cos(np.pi/6), yc + R*np.sin(np.pi/6))

    start_t = inv_parametric_circle(start_point[0], xc, R)
    end_t   = inv_parametric_circle(end_point[0], xc, R)

    arc_T = np.linspace(start_t, end_t, N)

    X,Y = parametric_circle(arc_T, xc, yc, R)
    Z=[z]*N
    x_all.extend(X)
    y_all.extend(Y)
    z_all.extend(Z)
    ax.scatter(X,Y,Z)
    ax.scatter([0],[yc],[z],color='r')

    ## 0 side
    ax.scatter(R+np.linspace(0,5,50),[0]*50,[z]*50)
    ax.scatter((R+np.linspace(0,5,50))*np.cos(np.pi/6),(R+np.linspace(0,5,50))*np.sin(np.pi/6),[z]*50)

    if z==0 or z==88:
        for offset in np.arange(0,5,0.1):
            R=R_z+10+offset-R_z*np.cos(theta)
            xc = 0.0 # center x
            yc = 0.0 # center y
            start_point = (xc + R*np.cos(0), yc + R*np.sin(0))
            end_point   = (xc + R*np.cos(np.pi/6), yc + R*np.sin(np.pi/6))

            start_t = inv_parametric_circle(start_point[0], xc, R)
            end_t   = inv_parametric_circle(end_point[0], xc, R)

            arc_T = np.linspace(start_t, end_t, N)

            X,Y = parametric_circle(arc_T, xc, yc, R)
            Z=[z]*N
            ax.scatter(X,Y,Z)

for z in np.arange(0,89,1):
    theta=np.arctan2(z,-xc_z)
    R=R_z+15-R_z*np.cos(theta)
    xc = 0.0 # center x
    yc = 0.0 # center y
    start_point = (xc + R*np.cos(0), yc + R*np.sin(0))
    end_point   = (xc + R*np.cos(np.pi/6), yc + R*np.sin(np.pi/6))

    start_t = inv_parametric_circle(start_point[0], xc, R)
    end_t   = inv_parametric_circle(end_point[0], xc, R)

    arc_T = np.linspace(start_t, end_t, N)

    X,Y = parametric_circle(arc_T, xc, yc, R)
    Z=[z]*N
    ax.scatter(X,Y,Z)
    ax.scatter([0],[yc],[z],color='r')
plt.axis('equal')
plt.show()


''' Spectrum_fitter.py : an obect-oriented framework for fitting dielectric spectra. '''
from numpy import *
import matplotlib.pyplot as plt
from scipy import optimize
from scipy import special as sp

class Lineshape:
    """Class that holds some things common to all Lineshapes"""
    def __init__(self,params,bounds,name):
        self.p = params
        self.bounds = bounds
        self.name = name

class Debye(Lineshape):
    """Debye lineshape object.
    Note: the wD parameter is assumed to be in units of cm^-1
    """
    def __init__(self,params=[1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="Debye"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wD"]
        self.type = "Debye"

    def __call__(self, w):
        rp = self.p[0]*self.p[1]**2/(self.p[1]**2 + w**2)
        cp = rp*w/self.p[1]
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return self.p[1]

    def print_params(self):
        print(u"%20s f =%7.5f \u03C9 = %6.2f 1/cm (%5.2f ps)" % (self.name, self.p[0], self.p[1], 33.34/(2*3.14159*self.p[1])))

    def print_params_latex(self):
        print(u"%20s & %7.5f & %6.2f & %5.2f &   & \\\\" % (self.name, self.p[0], self.p[1], 33.333/(2*3.14159*self.p[1])))

class DHO(Lineshape):
    """Damped harmonic oscillator object"""
    def __init__(self,params=[1,1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="DHO"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "w", "gamma"]
        self.type = "DHO"

    def __call__(self, w):
        denom = (self.p[1]**2 - w**2)**2 + w**2*self.p[2]**2
        rp = self.p[0]*(self.p[1]**2)*(self.p[1]**2 - w**2)/denom
        cp = self.p[0]*(self.p[1]**2)*self.p[2]*w/denom
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print(u"%20s f =%7.5f \u03C9 = %6.2f + %6.2f i  (%6.3f ps)" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/(2*3.141*self.p[1])))

    def print_params_latex(self):
        print(u"%20s & %7.5f &  %6.2f & %6.3f & %6.2f &  \\\\" % (self.name, self.p[0], self.p[1], 33.34/(2*3.141*self.p[1]), self.p[2] ))

class BrendelDHO(Lineshape):
    """"Brendel model for amorphous materials - Gaussian distribution of DHOs. Ref: J. Appl. Phys. 71, 1 (1992)"""
    def __init__(self,params=[1,1,1,1],bounds=[(0,+float('inf')),(0,+float('inf')),(0,+float('inf')),(0,+float('inf'))],name="BrendelDHO"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["wp**2/w0**2", "wT", "gamma","sigma"]
        self.type = "BrendelDHO"
        self.f = 0

    def __call__(self, w):
        sigma = self.p[3]
        x0 = self.p[1]
        g = self.p[2]
        a = sqrt(w**2 - 1j*g*w)
        a = a.real - 1j*a.imag #we want the imaginary part to the root to be positive
        prefac = 1j*sqrt(3.14149)*self.p[0]*x0**2/(sqrt(22)*sigma)
        eps = prefac*exp(-.5)*(1/a)*( sp.erfcx(-1j*(a-x0)/sigma) +  sp.erfcx(-1j*(a+x0)/sigma) )
        #self.f = 2*prefac*exp(-x0**2/(2*sigma**2))*(1 + sp.erf(1j*x0/sigma))
        self.f = eps.real[1]
        return (eps.real, eps.imag)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9 = %6.2f + %6.2f i  (%5.3f ps) \u03C3 = %6.2f cm^-1" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/self.p[1], self.p[3]))

    def print_params_latex(self):
        print( u"%20s & %7.5f & %6.2f & %5.3f & %6.2f  & %6.2f \\\\" % (self.name, self.p[0], self.p[1], 33.34/self.p[1], self.p[2], self.p[3]))

class DistributionOfDebye(Lineshape):
    '''Under construction'''

    def __init__(self,params=[1,1],bounds=[(0,+float('inf')),(0,+float('inf'))],name="BrendelDHO"):
        Lineshape.__init__(self, params, bounds, name)
        #self.pnames = ["wp**2/w0**2", "wT", "gamma","sigma"]
        #self.type = "BrendelDHO"
        #self.f = 0
        #self.num_tau_pts=10000
        ##self.min_tau=
        ##self.max_tau=

        #tau_values = logspace(min_tau, max_tau, num_tau_pts)

        #def __call__(self, w):

        #for m in xrange(1,num_tau_pts+1):
            #gtau(m)*tau

        #def TikhonovRegularization(self):
        #der1 = gradient(gdist)
        #der2 = gradient(der1)
        #return linalg.norm(der2)**2

class StretchedExp(Lineshape):
    """Stretched Exponential lineshape """
    def __init__(self,params=[1,1,1],bounds=[(0,10000),(0,10000),(0,1)],name="Str exp"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "tau", "beta"]
        self.type = "StretchedExp"

    def __call__(self, w):
        (f, eps_omega) = self.calc_eps(w)
        rp = interp(w,f,real(eps_omega))
        cp = interp(w,f,imag(eps_omega))
        return (rp, cp)

    def calc_eps(self,w):
        deltaeps = self.p[0]
        tau = self.p[1]
        beta = self.p[2]
        timestep = 1/(2*3.141*max(w)) #timestep in ps
        maxt = 3*tau #length of corr function
        npts = int(maxt/timestep)
        times = array(range(0,npts))*timestep
        corr_fun = exp(-(times/tau)**beta)
        nextpow2 = int(2**ceil(log2(npts)))
        f = (1/(2.99*.01))*array(range(0,npts))/(timestep*nextpow2) #Frequencies (evenly spaced), inverse cm
        tderiv = -diff(corr_fun)/timestep #time derivative of corr fun
        eps_omega = deltaeps*ifft(tderiv,nextpow2) #inverse one-sided fourier
        return (f, eps_omega[0:npts])

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9 %6.2f 1/cm (%5.2f ps) \u03B2 = %6.2f" % (self.name, self.p[0], self.p[1], 33.34/(self.p[1]), self.p[2] ))

class PowerLawDebye(Lineshape):
    """Debye lineshape with additional "power law" wing.
    See J. Phys. Chem. B, 2005, 109 (12), pp 6031-6035

    Note: the wD parameter is assumed to be in units of cm^-1
    """
    def __init__(self,params=[1,1],bounds=[(0,+float('inf')),(0,+float('inf')),(0,+float('inf')),(1,10)],name="unnamed"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wD","A","q"]
        self.type = "PowerLawDebye"
        self.convfac = 1.0#/(2*3.141*2.99*.01)

    def __call__(self, w):
        A = self.p[2]
        q = self.p[3]
        tau = self.convfac/self.p[1]
        numomegas = len(w)
        start  = numomegas - len(w[w[:] > self.p[1]])
        HighFreqOmegas = w#0.0*array(w)
        #HighFreqOmegas[start:numomegas] = w[start:numomegas]
        TheWing = 1 + A*(HighFreqOmegas*tau)**q
        rp = TheWing*self.p[0]/(1 + (tau*w)**2)
        cp = TheWing*self.p[0]*w*tau/(1 + (tau*w)**2)
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return self.p[1]

    def print_params(self):
        print(u"%20s f =%7.5f \u03C9 %6.2f 1/cm (%5.2f ps) A = %6.2f q = %6.2f" % (self.name, self.p[0], self.p[1], 33.34/self.p[1], self.p[2], self.p[3] ))

class ColeCole(Lineshape):
    """Cole-Cole lineshape object.

    Note: the wD parameter is assumed to be in units of cm^-1
    """
    def __init__(self,params=[1,1,1],bounds=[(0,+float('inf')),(0,+float('inf')),(0,2)],name="unnamed"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wD","alpha"]
        self.type = "Debye"

    def __call__(self, w):
        rp = self.p[0]*self.p[1]**2/(self.p[1]**2 + w**2)
        cp = rp*w/self.p[1]
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return self.p[1]

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9 %6.2f 1/cm (%5.2f ps) \u03B1 %6.2f" % (self.name, self.p[0], self.p[1], 33.34/self.p[1], self.p[2] ))

class VanVleck(Lineshape):
    """Van Vleck and Weisskopf lineshape Rev. Mod. Phys., 17:227 236, Apr 1945."""
    def __init__(self,params=[1,1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="VanVleck"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wT","gamma"]
        self.type = "VanVleck"

    #the real part has not been tested or checked to see if it is mathematically correct!!!
    def __call__(self, w):
        rp = .5*self.p[0]*(self.p[1]**2 + self.p[2]**2)( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        cp = .5*self.p[0]*self.p[2]*w*( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9= %6.2f + %6.2f i  %6.3f ps" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/(2*3.141*self.p[2]))    )

class Gaussian(Lineshape):
    """Gaussian peak in the imaginary part, ie. inertial absorption or homogenous broadening"""
    def __init__(self,params=[1,1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="Gaussian"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wT","gamma"]
        self.type = "BRO"

    def __call__(self, w):
        # sp.dawsn
        rp = .5*self.p[0]*(self.p[1]**2 + self.p[2]**2)( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        cp = .5*self.p[0]*self.p[2]*w*( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9= %6.2f + %6.2f i  %6.3f" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/(2*3.141*self.p[2])))

class constant(Lineshape):
    """this "lineshape" object is merely a constant term"""
    def __init__(self,params=[1],bounds=[(0,100)],name="constant"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["Eps float('inf')."]
        self.type = "Constant"

    def __call__(self,w):
        rp = 0*w + self.p[0]
        cp = 0*w
        return (rp, cp)

    def print_params(self):
        print("%20s f =%7.5f" % (self.name, self.p[0]))

    def print_params_latex(self):
        print("%20s & %7.5f & & & & \\\\" % (self.name, self.p[0]))

#-----------------------------------------------------------------------------------------------------------
def fit_model_gLST_constraint(modelL, modelT, dataX, Tdatarp, Tdatacp):
        ''' fit both the transverse and longitudinal models at the same time with the gLST constraint  '''

        Ldatarp = 1.0 - Tdatarp/(Tdatarp**2 + Tdatacp**2)
        Ldatacp = Tdatacp/(Tdatarp**2 + Tdatacp**2)

        def diffsq(paramsL, paramsT):

            modelL.setparams(paramsL)
            modelT.setparams(paramsT)

            (Lrp, Lcp) = modelL(dataX)
            (Trp, Tcp) = modelT(dataX)

            Ldiff = (Ldatarp - Lrp)/Ldatarp + (Ldatacp - Lcp)/Ldatacp
            Tdiff = (Tdatarp - Trp)/Tdatarp + (Tdatacp - Tcp)/Tdatacp

            err = dot(Tdiff, Tdiff) + dot(Ldiff, Ldiff)

            return err

        def costfun(params):
            """Wrapper function needed for differential_evolution()

            Args:
                params: a list of parameters for the model
            Returns:
                The cost function
            """

            paramsL = params[0:len(params)//2]
            paramsT = params[len(params)//2:]

            eps0    = Tdatarp[0]
            eps_inf = Tdatarp[-1]

            fsumpenalty = ( ( eps0 - modelT.fsum())/Tdatarp[0] )**2

            gLST_RHS = eps0/eps_inf

            gLSTpenalty = ( gLST_LHS(modelL, modelT) - gLST_RHS )**2

            #print(diffsq(paramsL, paramsT) , gLSTpenalty , 100*fsumpenalty)

            return diffsq(paramsL, paramsT)  + 100*fsumpenalty + gLSTpenalty

        Lparams = modelL.getparams()
        Tparams = modelT.getparams()

        params = Lparams + Tparams

        boundsL = modelL.getbounds()
        boundsT = modelT.getbounds()

        bounds = boundsL + boundsT

        assert len(boundsL) == len(boundsT)
        assert len(params) == len(bounds)

        resultobject = optimize.minimize(costfun, x0=params, bounds=bounds, method='TNC')
        print("number of iterations = ", resultobject.nit)

        resultobject = optimize.minimize(costfun, x0=params, bounds=bounds, method='SLSQP')
        print("number of iterations = ", resultobject.nit)

        #optimize.fmin_l_bfgs_b(costfun, bounds=bounds)
        #optimize.differential_evolution(costfun, bounds)

        Lparams = modelL.getparams()
        Tparams = modelT.getparams()

        print("RMS error = ",sqrt(diffsq(Lparams, Tparams)))

#----------------------------------------------------------------------------------------------------
def print_gLST_ratios(modelL, modelT):
    '''try to print out the ratios for different modes. Note this may not be very accurate as the ordering of modes in the longitudinal and transverse model
        may not be the same'''

    ratios = ones(modelL.numlineshapes)

    if (modelL.numlineshapes == modelT.numlineshapes):

        for i in range(modelL.numlineshapes):
            if modelL.lineshapes[i].type == "Debye":
                ratios[i] = modelL.lineshapes[i].p[1]/modelT.lineshapes[i].p[1]

            if (modelL.lineshapes[i].type == "DHO") or (modelL.lineshapes[i].type == "VanVleck") or (modelL.lineshapes[i].type == "BrendelDHO"):
                ratios[i] = (modelL.lineshapes[i].p[1]**2 + modelL.lineshapes[i].p[2]**2)/modelT.lineshapes[i].p[1]**2

        set_printoptions(precision=2)
        print("LST Ratios = ", ratios)
        print("Prod of ratios =", prod(ratios))
    else:
        print("Can't compute gLST ratios, number of lineshapes in transverse not equal to number in longitudinal")

#----------------------------------------------------------------------------------------------------
def gLST_LHS(modelL,modelT):
    '''calculate the left hand side of the GLST equation'''

    numerator   = ones(modelL.numlineshapes)
    denominator = ones(modelT.numlineshapes)

    for i in range(modelL.numlineshapes):
        if modelL.lineshapes[i].type == "Debye":
            numerator[i] = modelL.lineshapes[i].p[1]

        if (modelL.lineshapes[i].type == "DHO") or (modelL.lineshapes[i].type == "VanVleck") or (modelL.lineshapes[i].type == "BrendelDHO"):
            numerator[i] = (modelL.lineshapes[i].p[1]**2 + modelL.lineshapes[i].p[2]**2)

    for i in range(modelT.numlineshapes):
        if modelT.lineshapes[i].type == "Debye":
            denominator[i] = modelT.lineshapes[i].p[1]

        if (modelT.lineshapes[i].type == "DHO") or (modelT.lineshapes[i].type == "VanVleck") or (modelT.lineshapes[i].type == "BrendelDHO"):
            denominator[i] = modelT.lineshapes[i].p[1]**2

    return prod(numerator)/prod(denominator)

##----------------------------------------------------------------------------------
##----- Printout all frequencies in system and left side of gLST equation  --------
##----------------------------------------------------------------------------------
def print_gLST_LHS_stuff(modelL, modelT, Tdatarp, Tdatacp):

    print("longitudinal model:")
    modelL.print_model()
    print("transverse model:")
    modelT.print_model()

    print_gLST_ratios(modelL, modelT)

    eps0    = Tdatarp[0]
    eps_inf = Tdatarp[-1]
    gLST_RHS = eps0/eps_inf

    print("LST LHS = %6.2f" % gLST_LHS(modelL,modelT))
    print("LST RHS = %6.2f" %  gLST_RHS)

#-------------------------------------------------------------------------------------------------------------
def plot_model(model,dataX,dataYrp,dataYcp,Myhandle,xmin=None,xmax=None,xscale='linear',yscale='log',ymin=None,ymax=None,show=False,Block=True,longitudinal=False,title='',peaks=[]):
    """displays a pretty plot of the real and complex parts of the model and data using matplotlib

    args:
        model: a spectral_model object
        dataX: a numpy array giving the experimental x-data
        dataYrp: a numpy array giving the real part of the experimental y-data
        dataYcp: a numpy array giving the complex part of the experimental y-data
        handle: an integer giving the plot window number
        xmin: scalar, minimum frequency to plot
        xmax: scalar, maximum frequency to plot
        xscale: string, xscale type 'linear' or 'log'
        yscale: string, yscale type 'linear' or 'log'
        show: logical, option to display plot
        blockoption: logical, option to block further processing after displaying window (Default True, False is experimental)
        """
    if (xmin == None):
        xmin = min(dataX)
    if (xmax == None):
        xmax = max(dataX)
    if (ymin == None):
        ymin = min(dataYrp)/600
    if (ymax == None):
        ymax = max(dataYrp)
    if (xscale == 'log'):
        plotomegas = logspace(log10(xmin), log10(xmax), 10000)
    else:
        plotomegas = linspace(xmin, xmax, 10000)

    #if (longitudinal == True):
    #    (rp, cp) = model.longeps(plotomegas)
    #    denom = dataYrp**2 + dataYcp**2
    #    (dataYrp,dataYcp) = (dataYrp/denom, dataYcp/denom)
    #    (xmin,xmax) = (min(dataX),max(dataX))
    #    (ymin,ymax) = (min(dataYrp),max(dataYrp))
    #else:
    (rp, cp) = model(plotomegas)

    # Two subplots, unpack the axes array immediately
    f, (ax1, ax2) = plt.subplots(nrows=2, sharex=True, sharey=False )

    ax1.plot(dataX, dataYrp, "g", plotomegas, rp,'b')
    #ax1.set_title('Real part')

    ax2.plot(dataX, dataYcp, "g", plotomegas, cp,'b')
    #ax2.set_title('Complex part')

    #plot all of the components
    for lineshape in model.lineshapes:
        (rpPart, cpPart) = lineshape(plotomegas)
        ax1.plot(plotomegas, rpPart ,'b--',linewidth=1)
        ax2.plot(plotomegas, cpPart ,'b--',linewidth=1)

    ax1.set_xscale(xscale)
    ax1.set_xlim([xmin,xmax])
    ax1.set_yscale(yscale)
    ax1.set_ylim([ymin,ymax])

    ax2.set_xscale(xscale)
    ax2.set_xlim([xmin,xmax])
    ax2.set_yscale(yscale)
    ax2.set_ylim([ymin,ymax])

    ax1.set_xlabel(r"$\omega$ (cm$^{-1}$)")
    ax2.set_xlabel(r"$\omega$ (cm$^{-1}$)")

    if (longitudinal == True):
        ax1.set_ylabel(r"Re$\lbrace\frac{1}{\varepsilon(\omega)}\rbrace$")
        ax2.set_ylabel(r"Im$\lbrace\frac{1}{\varepsilon(\omega)}\rbrace$")
    else:
        ax1.set_ylabel(r"Re$\lbrace\varepsilon(\omega)\rbrace$")
        ax2.set_ylabel(r"Im$\lbrace\varepsilon(\omega)\rbrace$")

    ax1.set_title(title)

   #ax.annotate('local max', xy=(3, 1),  xycoords='data')

#-----------------------------------------------------------------------
# Function to find the maxima of a dataset by looking where the sign of the slope changes
#-----------------------------------------------------------------------
def find_peaks(dataset,omegas):
    #Smooth dataset
    smoothing_length = 5
    dataset = np.convolve(dataset, np.ones(smoothing_length)/smoothing_length)

   # lowess = sm.nonparametric.lowess(dataset, omegas, frac=0.5)
    #dataset = lowess[:,1]

    npoints = len(dataset)
    data_shift = np.r_[0, dataset]
    diff = data_shift[0:npoints] - dataset
    peaks = []
    npoints = len(omegas) -1
    for i in range(0, npoints):
        if np.sign(diff[i]) != np.sign(diff[i+1]):
            #check if in useful range
            if ( 580 <= omegas[i] <= 1000 ) | ( 3000 <= omegas[i] <= 3500 ): #(1500 <= omegas[i] <= 1700)
                peaks =  peaks + [(omegas[i] + omegas[i+1])/2]
    return peaks


import pygtk
pygtk.require('2.0')
import gtk
import os
import stat
import shutil
import gobject
import gettext
import gnomevfs
from gnome import ui
from common.consts import *
from common.utils import get_icon_with_type
from common.widgets import TweakPage, DirView, FlatView
from common.widgets.dialogs import WarningDialog

(
    COLUMN_ICON,
    COLUMN_TITLE,
    COLUMN_PATH,
    COLUMN_EDITABLE,
) = range(4)

class AbstractScripts:
    systemdir = os.path.join(os.path.expanduser('~'), '.ubuntu-tweak/scripts')
    userdir = os.path.join(os.getenv('HOME'), '.gnome2', 'nautilus-scripts')

class DefaultScripts(AbstractScripts):
    '''This class use to create the default scripts'''
    scripts = {
            'copy-to': _('Copy to ...'),
            'copy-to-desktop': _('Copy to Desktop'),
            'copy-to-download': _('Copy to Download'),
            'copy-to-home': _('Copy to Home'),
            'move-to': _('Move to ...'),
            'move-to-desktop': _('Move to Desktop'),
            'move-to-download': _('Move to Download'),
            'move-to-home': _('Move to Home'),
            'link-to': _('Link to ...'),
            'link-to-desktop': _('Link to Desktop'),
            'link-to-download': _('Link to Download'),
            'link-to-home': _('Link to Home'),
            'open-with-gedit': _('Open with gedit'),
            'open-with-gedit-as-root': _('Open with gedit(as root)'),
            'browse-as-root': _('Browse as root'),
            'search-in-current': _('Search in current folder'),
            'convert-image-to-jpg': _('Convert image to JPG'),
            'convert-image-to-png': _('Convert image to PNG'),
            'convert-image-to-gif': _('Convert image to GIF'),
            'set-image-as-wallpaper': _('Set image as wallpaper'),
            }

    def create(self):
        if not os.path.exists(self.systemdir):
            os.makedirs(self.systemdir)
        for file, des in self.scripts.items():
            realname = '%s' % des
            if not os.path.exists(os.path.join(self.systemdir,realname)):
                shutil.copy(os.path.join(DATA_DIR, 'scripts/%s' % file), os.path.join(self.systemdir,realname))

    def remove(self):
        if not os.path.exists(self.systemdir):
            return
        if os.path.isdir(self.systemdir):
            for root, dirs, files in os.walk(self.systemdir, topdown=False):
                for name in files:
                    os.remove(os.path.join(root, name))
                for name in dirs:
                    os.rmdir(os.path.join(root, name))
                    os.rmdir(self.systemdir)
        else:
            os.unlink(self.systemdir)
        return

class EnableScripts(DirView, AbstractScripts):
    '''The treeview to display the enable scripts'''
    type = _('Enabled Scripts')

    def __init__(self):
        DirView.__init__(self, self.userdir)

    def do_update_model(self, dir, iter):
        for item in os.listdir(dir):
            fullname = os.path.join(dir, item)
            pixbuf = get_icon_with_type(fullname, 24)

            child_iter = self.model.append(iter)
            self.model.set(child_iter,
                              COLUMN_ICON, pixbuf,
                              COLUMN_TITLE, os.path.basename(fullname),
                              COLUMN_PATH, fullname,
                              COLUMN_EDITABLE, False)

            if os.path.isdir(fullname):
                self.do_update_model(fullname, child_iter)
            else:
                if not os.access(fullname, os.X_OK):
                    try:
                        os.chmod(fullname, stat.S_IRWXU)
                    except:
                        pass

class DisableScripts(FlatView, AbstractScripts):
    '''The treeview to display the system template'''
    type = _('Disabled Scripts')

    def __init__(self):
        FlatView.__init__(self, self.systemdir, self.userdir)

class Scripts(TweakPage, AbstractScripts):
    '''Freedom added your docmuent scripts'''
    def __init__(self):
        TweakPage.__init__(self,
                _('Manage Scripts'),
                _("You can do all kinds of tasks with scripts.\nYou can drag and drop from File Manager.\n'Scripts' will be added to the context menu."))

        self.default = DefaultScripts()
        self.config_test()

        hbox = gtk.HBox(False, 10)
        self.pack_start(hbox)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.pack_start(sw)

        self.enable_scripts = EnableScripts()
        sw.add(self.enable_scripts)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        hbox.pack_start(sw)

        self.disable_scripts = DisableScripts()
        sw.add(self.disable_scripts)

        hbox = gtk.HBox(False, 0)
        self.pack_start(hbox, False, False, 10)

        button = gtk.Button(_('Rebuild System Scripts'))
        button.connect('clicked', self.on_rebuild_clicked)
        hbox.pack_end(button, False, False, 5)

        self.enable_scripts.connect('drag_data_received', self.on_enable_drag_data_received)
        self.enable_scripts.connect('deleted', self.on_enable_deleted)
        self.disable_scripts.connect('drag_data_received', self.on_disable_drag_data_received)

    def on_enable_deleted(self, widget):
        self.disable_scripts.update_model()

    def on_enable_drag_data_received(self, treeview, context, x, y, selection, info, etime):
        self.disable_scripts.update_model()

    def on_disable_drag_data_received(self, treeview, context, x, y, selection, info, etime):
        self.enable_scripts.update_model()

    def on_rebuild_clicked(self, widget):
        dialog = WarningDialog(_('This will delete all disabled scripts.\nDo you wish to continue?'))
        if dialog.run() == gtk.RESPONSE_YES:
            self.default.remove()
            self.default.create()
            self.disable_scripts.update_model()
        dialog.destroy()

    def config_test(self):
        if not os.path.exists(self.systemdir):
            self.default.create()

if __name__ == '__main__':
    from utility import Test
    Test(Scripts)


import torch
import torch.nn as nn

class Net(nn.Module):
    def __init__(self, in_dim=100, hidden_dim=50, out_dim=10):
        super(Net, self).__init__()
        self.layer = nn.Sequential(
            nn.Linear(in_dim, hidden_dim),
            nn.BatchNorm1d(hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, out_dim)
        )
    def forward(self, x):
        # x = self.layer(x)
        for f in self.layer:
            x = f(x)
        return x

if __name__=='__main__':
    model = Net()
    x = torch.ones(2,100)
    # 网络中有BN层，在输入时应当输入两个或以上的样本
    # 如果输入x = torch.ones(1,100)时会报错
    y = model(x)
    print(y)


# coding=UTF-8

import random
import json
from libs.file.class_Excel import Excel
from applications.collegeAdmission.class_ceespidersina import CEESpiderSina

# 0. Initial configuration
valid_proxy = ['61.174.10.22:8080', '101.66.253.22:8080','61.174.13.12:80', '101.200.178.46:3128','101.226.249.237:80']

regions = ['北京','天津','上海','重庆','河北','河南','山东','山西','安徽','江西',
           '江苏','浙江','湖北','湖南','广东','广西','云南','贵州','四川','陕西',
           '青海','宁夏','黑龙江','吉林','辽宁','西藏','新疆','内蒙古','海南','福建',
           '甘肃']
subject = ['文科','理科']
year = ['2014','2013','2012','2011','2010','2009','2008']
batch = ['本科一批','本科二批','本科三批']

result = []

YEAR = year[0]
BATCH = batch[0]

# 1. 开始抓取Z
spider = CEESpiderSina(proxy=valid_proxy[random.randint(0,len(valid_proxy)-1)])
for region in regions[20:]:
    print(region)
    for sub in subject:
        spider.clear()
        print(sub)

        spider.select_region(region)
        spider.select_subject(sub)
        spider.select_year(YEAR)
        spider.select_batch(BATCH)
        spider.do_search()
        spider.get_result_and_more()

        file_name = ''.join(['E:/robot/files/college/exam/',region,'_',sub,'_',YEAR,'_',BATCH,'.txt'])
        json.dump(spider.colleges, fp=open(file_name,'w'))

spider.close()

'''
file = ''.join(['E:/robot/files/college/exam/','北京_理科_2014_本科一批','.txt'])
F = json.load(fp=open(file,'r'))
for item in F:
    print(item)
print(len(F))'''


import torch
import numpy as np
import pygame
import sys
from PIL import Image
import cv2
import time
from lib.utils.testing import decode_pred
pygame.init()

def make_a_char(font, c, color, back):
    try:
        ftext = font.render(c, True, color, back)
    except:
        ftext = font.render('卍', True, color, back)
    pygame.image.save(ftext, "p_char.jpg")
    try:
        p_im = Image.open('p_char.jpg')
    except:
        time.sleep(0.1)
        p_im = Image.open('p_char.jpg')
    return p_im

def tensor2image(inp):
    inp = inp.permute(0,2,3,1).squeeze()
    inp = inp.detach().cpu().numpy()
    return inp

def link_attn(attn):
    attn = [e.sum(1) for e in attn]
    attn_map = attn[-1]
    return attn_map.detach().cpu().numpy()

def num2char(line, converter):
    line = [converter.num2dict[i] for i in line]
    line = [i if len(i)==1 else '&' for i in line]
    line = ''.join(line).replace('$', '')
    line = list(line)
    return line

def attn_visual_img2str(inp, dec, pred, label, st, config, converter):
    attn_map = link_attn(dec)
    batchsize,L,T = attn_map.shape
    inp = inp.cpu().numpy()
    font = pygame.font.Font('lib/core/a.ttf', 25)

    for bi in range(batchsize):
        print('    Drawing R Attn {}'.format(bi+st*batchsize))
        im = inp[bi,0,:,:]
        im = 255*(im-np.min(im))/(np.max(im)-np.min(im))

        im_list = []

        p_line = decode_pred(config, pred[bi].int().detach().cpu().tolist(), converter)
        p_line = num2char(p_line, converter)
        t_line = num2char(label[bi], converter)

        for li in range(L):
            if li>=len(p_line) and li>=len(t_line):
                break
            img = im.copy()
            attn = attn_map[bi,li,:]
            attn = attn.reshape((4,4))
            attn = attn.repeat(8, axis=0).repeat(8, axis=1)
            attn = np.expand_dims(attn, axis=2).repeat(2, axis=2)
            attn *= 255
            attn_r = np.zeros((attn.shape[0],attn.shape[1],1))
            attn = np.concatenate([attn_r, attn], axis=-1)
            img = Image.fromarray(img).convert('RGB')
            img = np.array(img) * -1
            img = (img + attn) * -1

            for i in range(attn.shape[0]):
                for j in range(attn.shape[1]):
                    for k in range(3):
                        if img[i,j,k]>255:
                            img[i,j,k] = 255
                        if img[i,j,k]<0:
                            img[i,j,k] = 0
            img = Image.fromarray(np.uint8(img))

            p_char = p_line[li] if li<len(p_line) else ' '
            t_char = t_line[li] if li<len(t_line) else ' '
            color = (0,200,0) if p_char==t_char else (200,0,0)

            p_im = make_a_char(font, p_char, color, (255,255,255))
            t_im = make_a_char(font, t_char, (0,0,0), (255,255,255))
            im_list.append([img, p_im, t_im])

        back = Image.new('RGB', (32+54, 32*len(im_list)), (255,255,255))
        for idx,(img, p_im, t_im) in enumerate(im_list):
            back.paste(img, (0,idx*32))
            back.paste(p_im, (32+2,idx*32))
            back.paste(t_im, (32+2+25+2,idx*32))
        back.save(config.MODEL.RESULT_SAVE_PATH + '/visual_R_{}.jpg'.format(bi+st*batchsize))

def attn_map_img2str(inp, dec, pred, label, st, config, converter):
    font = pygame.font.Font('lib/core/a.ttf', 26)
    attn_map = link_attn(dec)
    B,L,T = attn_map.shape
    inp = tensor2image(inp)

    for bi in range(B):
        print('    Drawing R map {}'.format(bi+st*B))
        p_line = decode_pred(config, pred[bi].int().detach().cpu().tolist(), converter)
        p_line = num2char(p_line, converter) + ['E']
        lens = len(p_line)
        back = Image.new('RGB', (lens*32+35, 16*32+35), (255,255,255))

        block = np.ones((8,8,3),dtype=np.float32) * 50
        block[:,:,1:] *= -1
        im = inp[bi]
        src = 255*(im-np.min(im))/(np.max(im)-np.min(im))

        src = np.expand_dims(src, axis=-1).repeat(3, axis=-1)
        for i in range(16):
            im = src.copy()
            x = i//4
            y = i%4
            im[x*8:(x+1)*8,y*8:(y+1)*8] += block
            im = np.clip(im,0,255)
            im = Image.fromarray(np.uint8(im))
            back.paste(im,(0,i*32))

        for i,c in enumerate(p_line):
            im = make_a_char(font, c, (0,0,0), (255,255,255))
            back.paste(im, (35+i*32+3,16*32+3))

        attn = attn_map[bi,:lens,:].transpose()
        attn = attn.repeat(32,axis=0).repeat(32,axis=1)
        attn = np.expand_dims(attn, -1)
        attn = 255 - attn.repeat(2,axis=2) * 255
        attn = np.clip(attn,0,255)
        red = np.ones((16*32,lens*32,1))*255
        attn = np.concatenate([red, attn], axis=-1)
        attn = np.uint8(attn)
        attn = Image.fromarray(attn)
        back.paste(attn, (35,0))
        back.save(config.MODEL.RESULT_SAVE_PATH + '/map_R_{}.jpg'.format(bi+st*B))

def attn_visual_str2img(inp, dec, pred, label, st, config, converter):
    font = pygame.font.Font('lib/core/a.ttf', 20)
    savepath = config.MODEL.RESULT_SAVE_PATH
    def make_line(line, score):
        line = line + ['B']
        L = len(line)
        new_score = np.zeros((L), dtype=np.float32)
        new_score[:-1] = score[:L-1]
        new_score[-1] = np.sum(score[L-1:])
        back = Image.new('RGB',(20*L,32),(255,255,255))
        for i,t in enumerate(line):
            BG = max(0, int(255*(1-new_score[i])))
            c_im = make_a_char(font, t, (0,0,0), (255, BG, BG))
            back.paste(c_im,(20*i,0))
        return back

    attn_map = link_attn(dec)
    B,L,T = attn_map.shape

    inp = tensor2image(inp)
    pred = tensor2image(pred)
    label = label.int().cpu().tolist()

    for bi in range(B):
        print('    Drawing G Attn {}'.format(bi+st*B))
        t_line = num2char(label[bi], converter)
        len_t = len(t_line)+1
        back = Image.new('RGB', (len_t*20+32,18*32), (255,255,255))
        inp_im = inp[bi]
        # inp_im = 250*(inp_im-np.min(inp_im))/(np.max(inp_im)-np.min(inp_im))
        inp_im = np.clip(inp_im / 0.0078125 + 128,0,255)
        inp_im = np.uint8(inp_im)
        inp_im = Image.fromarray(inp_im)
        back.paste(inp_im,(0,0))

        pred_im = pred[bi]
        # pred_im = 250*(pred_im-np.min(pred_im))/(np.max(pred_im)-np.min(pred_im))
        pred_im = np.clip(pred_im / 0.0078125 + 128,0,255)
        pred_im_copy = pred_im.copy()
        pred_im_copy = np.uint8(pred_im_copy)
        pred_im_copy = Image.fromarray(pred_im_copy)
        back.paste(pred_im_copy,(35,0))
        pred_im = pred_im * 0.5
        back.paste(inp_im,(0,0))

        for li in range(L):
            attn = attn_map[bi,li,:]
            attn_text = make_line(t_line, attn)
            h = li//4
            w = li%4
            pred_im_copy = pred_im.copy()
            pred_im_copy[h*8:(h+1)*8,w*8:(w+1)*8] = pred_im_copy[h*8:(h+1)*8,w*8:(w+1)*8]*2
            pred_im_copy = np.uint8(pred_im_copy)
            pred_paste = Image.fromarray(pred_im_copy)
            back.paste(pred_paste, (0,35 + li*32))
            back.paste(attn_text, (35,35+li*32))

        back.save(savepath + '/visual_G_{}.jpg'.format(bi+st*B))

def attn_map_str2img(inp, dec, pred, label, st, config, converter):
    font = pygame.font.Font('lib/core/a.ttf', 26)
    attn_map = link_attn(dec)
    B,L,T = attn_map.shape
    pred = tensor2image(pred)
    label = label.int().cpu().tolist()

    for bi in range(B):
        print('    Drawing G Map {}'.format(bi+st*B))
        p_line = num2char(label[bi], converter) + ['B']
        lens = len(p_line)
        back = Image.new('RGB', (lens*32+35, 16*32+35), (255,255,255))

        block = np.ones((8,8,3),dtype=np.float32) * 50
        block[:,:,1:] *= -1
        im = pred[bi]
        src = 255*(im-np.min(im))/(np.max(im)-np.min(im))
        src = np.expand_dims(src, axis=-1).repeat(3, axis=-1)
        for i in range(16):
            im = src.copy()
            x = i//4
            y = i%4
            im[x*8:(x+1)*8,y*8:(y+1)*8] += block
            im = np.clip(im,0,255)
            im = Image.fromarray(np.uint8(im))
            back.paste(im,(0,i*32))

        for i,c in enumerate(p_line):
            im = make_a_char(font, c, (0,0,0), (255,255,255))
            back.paste(im, (35+i*32+3,16*32+3))

        attn = attn_map[bi,:,:lens]
        attn = attn.repeat(32,axis=0).repeat(32,axis=1)
        attn = np.expand_dims(attn, -1)
        attn = 255 - attn.repeat(2,axis=2) * 255
        attn = np.clip(attn,0,255)
        red = np.ones((16*32,lens*32,1))*255
        attn = np.concatenate([red, attn], axis=-1)
        attn = np.uint8(attn)
        attn = Image.fromarray(attn)
        back.paste(attn, (35,0))
        back.save(config.MODEL.RESULT_SAVE_PATH + '/map_G_{}.jpg'.format(bi+st*B))


import threading

from pywb.webapp.pywb_init import create_wb_router
from pywb.framework.wsgi_wrappers import init_app

# disable is_hop_by_hop restrictions
import wsgiref.handlers
wsgiref.handlers.is_hop_by_hop = lambda x: False

class ServerThreadRunner(object):
    def __init__(self, make_httpd, config_file=None):

        if config_file:
            self.app = init_app(create_wb_router,
                                load_yaml=True,
                                config_file=config_file)
        else:
            self.app = None

        self.httpd = make_httpd(self.app)
        self.port = self.httpd.socket.getsockname()[1]

        proxy_str = 'http://localhost:' + str(self.port)
        self.proxy_str = proxy_str
        self.proxy_dict = {'http': proxy_str,
                           'https': proxy_str}

        def run():
            self.httpd.serve_forever()

        self.thread = threading.Thread(target=run)
        self.thread.daemon = True
        self.thread.start()

    def stop_thread(self):
        self.httpd.shutdown()


#!/usr/bin/python3
########################
# SCSU email scraper geolocation via google maps
# James Otten 2014
########################

import requests
from scraperdb import ScraperDatabase
import logging
import configparser
import sys

class Point:
  def __init__(self, lat, lon, formatted):
    self.lat = lat
    self.lon = lon
    self.formatted = formatted

class Geolocation:
  def __init__(self, db, GOOGLE_API_KEY):
    self.db = db
    self.GOOGLE_API_KEY = GOOGLE_API_KEY

  def do_lookup(self, count=1):
    rows = self.db.get_empty_addresses(count)
    print(rows)
    for row in rows:
      point = self.get_google_maps(row[1])
      if point != None:
        self.db.add_geolocation(row[0], point.lat, point.lon, point.formatted)
        print('%s -> %s' % (row[1].replace('\n',','), point.formatted))
        print('%s -> lat:%s lon:%s'%(row[1].replace('\n',','), point.lat, point.lon))
      else:
        msg = 'Could not log: %s'%row[0]
        logging.warn(msg)
        print(msg)

  def get_google_maps(self, address):
    try:
      url = 'https://maps.googleapis.com/maps/api/geocode/json'
      param={'address':address, 'key':self.GOOGLE_API_KEY}
      req = requests.get(url,params=param)
      json = req.json()
      if json['status'] == 'OK':
        if len(json['results']) != 1:
          logging.warn('Multiple results for: %s'%address)
          return None
        lat = json['results'][0]['geometry']['location']['lat']
        lon = json['results'][0]['geometry']['location']['lng']
        formatted = json['results'][0]['formatted_address']
        if 'partial_match' in json['results'][0].keys() or 'PO BOX' in address.upper():
          formatted = address.replace('\n',', ')
        point = Point(lat, lon, formatted)
        return point
    except Exception as e:
      msg = 'get_google_maps: %s'%str(e)
      logging.error(msg)
      print(msg)
      return None

def main():
  logging.basicConfig(filename='Geo.log', level=logging.DEBUG)
  try:
    count = 10
    if len(sys.argv) == 2:
      val = int(sys.argv[1])
      if val > 0:
        count = val
    config = configparser.RawConfigParser()
    config.read('SCSUStudentSearch.cfg')
    GOOGLE_API_KEY = config.get('gmaps','secret')
    db = ScraperDatabase()
    geo = Geolocation(db, GOOGLE_API_KEY)
    geo.do_lookup(count=10)
  except Exception as e:
    msg = 'External error: %s' % str(e)
    logging.error(msg)
    print(msg)

if __name__ == '__main__': main()


#!/usr/bin/python3
# -*- coding: utf-8 -*-

'''
此项目为堆石混凝土图像识别数据预处理软件
此代码主要完成GUI界面的搭建工作

最后编辑日期：2020-5-14
'''

import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from skimage import io
import numpy as np
import correct
import count
from segmentation import watershed
from label_show import MyLabel
from sub_window import SegWindow, CorrectWindow, BodyWindow
import file

class ImgSegmentation(QMainWindow):
    '''
    主窗口类
    '''
    def __init__(self):
        '''
        构造函数
        '''
        super().__init__()
        self.filepath = ''  #存储处理文件路径
        self.filetype = ''  #存储文件类型
        self.img = np.zeros(1)  #存储图片的原始信息

        self.labels = None  #存储分割面的标记信息
        self.surfaces = None  #存储每个分割面的信息，包括连通域以及轮廓，可以理解为每一个分割面为一个图层
        self.polygon = []  #存储分割后分割面的轮廓信息

        self.labels_body = None  #存储块体的标注信息
        self.polygon_body = []  #存储块体的轮廓信息
        self.surfaces_body = None  #存储每一个块体的信息，包括连通域以及轮廓，可以理解为一个块体为一个图层

        self.coordinate_label = None  #坐标，参考系为label
        self.coordinate_img = None  #坐标，参考系为图片
        self.body_process = False  #标记是否进入块体对应阶段的指示变量
        self.relation = None  #存储堆石面与堆石之间对应关系

        self.init_ui()

    def init_ui(self):
        '''
        这是主窗口的构造函数

        初始化模块：
        菜单栏
        状态栏
        图像显示区域
        '''

        self.setGeometry(0, 50, 900, 900)  #设置窗口大小及位置
        self.setWindowTitle('图像处理')  #设置窗口标题

        self.seg_window = SegWindow()  #定义分割工具栏
        self.correct_window = CorrectWindow()  #定义人工修正工具栏
        self.body_window = BodyWindow()  #定义块体对应工具栏

        #设置菜单栏
        open_act = QAction('打开图片', self)
        open_act.setShortcut('Ctrl+O')
        open_act.setStatusTip('打开图片')
        open_act.triggered.connect(self.openimage)

        exit_act = QAction('退出', self)
        exit_act.setShortcut('Ctrl+Q')
        exit_act.setStatusTip('退出应用程序')
        exit_act.triggered.connect(self.close)

        seg_act = QAction('分割图片', self)
        seg_act.setShortcut('Ctrl+A')
        seg_act.setStatusTip('分割图片')
        seg_act.triggered.connect(self.seg_window.show)

        edit_act = QAction('修改结果', self)
        edit_act.setShortcut('Ctrl+E')
        edit_act.setStatusTip('再分割、合并过分割区域、背景删除')
        edit_act.triggered.connect(self.correct_window.show)

        body_act = QAction('块体对应', self)
        body_act.setShortcut('Ctrl+B')
        body_act.setStatusTip('堆石面与堆石体的对应')
        body_act.triggered.connect(self.body_window.show)

        save_act = QAction('输出结果', self)
        save_act.setShortcut('Ctrl+S')
        save_act.setStatusTip('保存结果文件')
        save_act.triggered.connect(self.save_file)

        menubar = self.menuBar()
        file_menu = menubar.addMenu('文件')
        file_menu.addAction(open_act)
        file_menu.addAction(exit_act)
        tool_menu = menubar.addMenu('工具')
        tool_menu.addAction(seg_act)
        tool_menu.addAction(edit_act)
        tool_menu.addAction(body_act)
        tool_menu.addAction(save_act)

        #设置状态栏
        self.statusBar().showMessage('请选择图片')

        #设置图像显示区域
        self.label = MyLabel(self)
        self.label.setFixedSize(800, 800)
        self.label.move(50, 50)

        #操作
        self.seg_window.startbtn.clicked.connect(self.watershed)
        self.correct_window.mergebtn.clicked.connect(self.correct_merge)
        self.correct_window.splitbtn2.clicked.connect(self.correct_split)
        self.correct_window.deletebtn.clicked.connect(self.correct_delete)
        self.correct_window.splitbtn.clicked.connect(self.select_surface)
        self.body_window.bodybtn.clicked.connect(self.surfaces_to_body)

        self.show()

    def openimage(self):
        '''
        这是打开文件的函数
        调用文件对话框
        显示图片
        更新状态栏显示文字
        '''
        #打开图片
        self.statusBar().showMessage('打开图片')
        img_name_open, img_type = QFileDialog.getOpenFileName(self, "打开图片", \
                                                           "", "*.jpg;;*.png;;All Files(*)")

        #显示图片
        jpg = QtGui.QPixmap(img_name_open).scaled(self.label.width(),\
                                               self.label.height(), Qt.KeepAspectRatio)
        self.filepath = img_name_open
        self.filetype = img_type
        self.label.setPixmap(jpg)

        self.statusBar().showMessage('请调整右侧参数')

        #指示变量修改
        self.label.show_body = False  #关闭块体轮廓显示
        self.label.show_contour = False  #关闭堆石面轮廓显示
        self.body_process = False  #关闭块体对应过程

    def watershed(self):
        '''
        分水岭分割流程的实现
        '''
        self.statusBar().showMessage('正在分割')  #状态栏提示

        #执行分水岭算法
        self.labels, self.img = watershed(self.filepath, self.seg_window.qle_median.text(),\
                  self.seg_window.local_th.isChecked(), self.seg_window.qle_thresh.text(),\
                  self.seg_window.qle_setoff.text(), self.seg_window.qle_erosion.text(),\
                  self.seg_window.qle_gradient.text())

        self.paint_contours()  #画边界框

        self.statusBar().showMessage('分水岭算法已完成！')  #更改状态栏

    def paint_contours(self):
        '''
        绘制由分水岭算法得到的边界框
        '''
        #分割面初始化
        self.surfaces = correct.surfaces_init(self.labels)

        #提取分割面信息中的轮廓信息
        self.polygon = [] #清空轮廓信息
        for surface in self.surfaces:
            for contour in surface[1:]:
                self.polygon.append(correct.coordinate_img_to_window(contour, self.img))

        self.label.polygon = self.polygon  #将主窗口中的轮廓数据传输至label中进行绘制工作

        self.label.show_contour = True  #打开label中的堆石面轮廓显示

    def correct_merge(self):
        '''
        进行过分割区域的合并
        '''
        #坐标
        coordinate_label = np.array(self.label.clk_pos)  #获得鼠标点击的label坐标
        coordinate_img = correct.coordinate_window_to_img(coordinate_label, \
                                                            self.img)  #将label坐标转换为图片坐标

        #进行分割面的合并
        self.labels, self.surfaces = correct.merge(coordinate_img, self.labels, self.surfaces)

        #提取分割面信息中的轮廓信息
        self.polygon = []
        for surface in self.surfaces:
            for contour in surface[1:]:
                self.polygon.append(correct.coordinate_img_to_window(contour, self.img))
        self.label.polygon = self.polygon  #将主窗口中的轮廓数据传输至label中进行绘制工作

        self.label.clk_pos = []  #清空鼠标点击位置

        #指示变量修改
        self.label.show_contour = True  #打开label中的堆石面轮廓显示
        self.label.point_isshow = False  #关闭鼠标点击位置显示

    def select_surface(self):
        '''
        进行欠分割区域的选择
        '''
        #坐标
        self.coordinate_label = np.array(self.label.clk_pos)  #获得鼠标点击的label坐标
        self.coordinate_img = correct.coordinate_window_to_img(self.coordinate_label, \
                                                                self.img)  #将label坐标转换为图片坐标

        #指示变量修改
        self.label.is_draw_line = True  #打开鼠标轨迹显示
        self.label.point_isshow = False  #关闭鼠标点击位置显示
        self.label.clk_pos = []  #清空鼠标点击位置

        self.correct_window.splitbtn2.setEnabled(True)  #激活“再分割”按钮

    def correct_split(self):
        '''
        进行欠分割区域的分割
        '''
        #判断鼠标轨迹是否存在，如果不存在将不进行任何操作，确保在忘记绘制曲线时，点击“再分割”按钮不会导致程序崩溃
        if self.label.pos_xy:
            #坐标
            pos = np.array(self.label.pos_xy)  #获得鼠标轨迹的label坐标
            line = correct.coordinate_window_to_img(pos, self.img)  #将鼠标轨迹label坐标转换为图片坐标

            #区域分割
            self.labels, self.surfaces = correct.split(self.coordinate_img, line, \
                                                       self.labels, self.surfaces)

            self.polygon = []  #清空轮廓信息
            #提取轮廓信息
            for surface in self.surfaces:
                for contour in surface[1:]:
                    self.polygon.append(correct.coordinate_img_to_window(contour, self.img))

            self.label.polygon = self.polygon  #将主窗口中的轮廓数据传输至label中进行绘制工作
            self.label.clk_pos = []  #清空鼠标点击位置
            self.label.pos_xy = []  #清空鼠标轨迹信息

            #指示变量修改
            self.label.show_contour = True  #打开label中的堆石面轮廓显示
            self.label.point_isshow = False  #关闭鼠标点击显示
            self.label.is_draw_line = False  #关闭鼠标轨迹显示
            self.correct_window.splitbtn2.setEnabled(False)  #失活再分割坐标

    def correct_delete(self):
        '''
        背景区域的删除
        '''
        #坐标
        self.coordinate_label = np.array(self.label.clk_pos)  #获得鼠标点击的label坐标
        self.coordinate_img = correct.coordinate_window_to_img(self.coordinate_label, \
                                                               self.img)  #将label坐标转换为图片坐标

        #区域删除
        self.labels, self.surfaces = correct.delete(self.coordinate_img, \
                                                    self.labels, self.surfaces)

        #提取轮廓信息
        self.polygon = []
        for surface in self.surfaces:
            for contour in surface[1:]:
                self.polygon.append(correct.coordinate_img_to_window(contour, self.img))
        self.label.polygon = self.polygon  #将主窗口中的轮廓数据传输至label中进行绘制工作

        self.label.clk_pos_delete += self.label.clk_pos  #将此次鼠标点击位置添加至删除位置记录中
        self.label.clk_pos = []  #清空鼠标点击位置

        #指示变量更改
        self.label.show_contour = True  #打开label中的堆石面轮廓显示
        self.label.point_isshow = False  #关闭鼠标点击显示
        self.label.point_delete = True  #打开删除位置记录显示

    def surfaces_to_body(self):
        '''
        块体和堆石面的对应
        '''
        #如果是第一次进行对应操作，应将原有的堆石分割面信息传递给堆石块体信息
        if not self.body_process:
            self.labels_body = np.array(self.labels, dtype=int)
            self.surfaces_body = list(self.surfaces)
            self.body_process = True

        #坐标
        coordinate_label = np.array(self.label.clk_pos)  #获得鼠标点击的label坐标
        coordinate_img = correct.coordinate_window_to_img(coordinate_label, \
                                                            self.img)  #将label坐标转换为图片坐标

        # 进行块体对应操作
        self.labels_body, self.surfaces_body = correct.body(coordinate_img, \
                                                            self.labels_body, self.surfaces_body)

        #轮廓信息提取
        self.polygon_body = []
        for surface_body in self.surfaces_body:
            for contour_body in surface_body[1:]:
                self.polygon_body.append(correct.coordinate_img_to_window(contour_body, self.img))
        self.label.polygon_body = self.polygon_body  #将主窗口中的轮廓数据传输至label中进行绘制工作

        self.label.clk_pos = []  #清空鼠标点击位置

        #指示变量更改
        self.label.show_contour = True  #打开label中的堆石面轮廓显示
        self.label.show_body = True  #打开label中的堆石体轮廓显示
        self.label.point_isshow = False  #关闭鼠标点击显示

    def save_file(self):
        '''
        保存输出文件
        '''
        #外切圆的计算
        circles, img = count.circle(self.surfaces_body, self.img)

        #确定文件输出位置
        img_name_s, img_type = QFileDialog.getSaveFileName(self, "保存图片", "",\
                                                            self.filetype)

        #文件保存
        io.imsave(img_name_s, img)  #外切圆绘制图片保存
        np.savetxt(img_name_s[:-3]+'txt', self.labels, fmt='%i')  #堆石面标记信息保存
        file.save_file(img_name_s, self.labels, self.labels_body, circles)  #堆石体对应信息和外接圆信息保存

    def closeEvent(self, event):
        '''
        关闭应用程序时弹出消息框
        '''
        reply = QMessageBox.question(self, 'Message',
                                     "确定要退出吗？", QMessageBox.Yes|
                                     QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

if __name__ == '__main__':

    APP = QApplication(sys.argv)
    ex = ImgSegmentation()
    sys.exit(APP.exec_())


import sys

def getch():
    import termios
    import sys, tty
    def _getch():
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(fd)
            ch = sys.stdin.read(1)
            if ch == '\u0003':
                sys.exit(0)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch
    return _getch()

import curses
import os

def main(win):
    win.nodelay(True)
    key=""
    win.clear()
    win.addstr("Detected key:")
    while 1:
        try:
           key = win.getkey()
           win.clear()
           win.addstr("Detected key:")
           win.addstr(str(key))
           if key == os.linesep:
              break
        except Exception as e:
           # No input
           pass

curses.wrapper(main)