def checkForNCNN() -> bool:
    """
    function that checks if the pytorch backend is available
    """
    try:
        from rife_ncnn_vulkan_python import Rife
        import ncnn

        try:
            from upscale_ncnn_py import UPSCALE
        except Exception:
            printAndLog(
                "Warning: Cannot import upscale_ncnn, falling back to default ncnn processing. (Please install vcredlist on your computer to fix this!)"
            )
        return True
    except ImportError as e:
        log(str(e))
        return False
    except Exception as e:
        log(str(e))

def checkForNCNN() -> bool:

    try:
        from rife_ncnn_vulkan_python import Rife
        import ncnn

        try:
            from upscale_ncnn_py import UPSCALE
        except Exception:
            printAndLog(
                "Warning: Cannot import upscale_ncnn, falling back to default ncnn processing. (Please install vcredlist on your computer to fix this!)"
            )
        return True
    except ImportError as e:
        log(str(e))
        return False
    except Exception as e:
        log(str(e))


def _to_a3m(sequences: Sequence[str]) -> str:
    """Converts sequences to an a3m file."""
    names = ["sequence %d" % i for i in range(1, len(sequences) + 1)]
    a3m = []
    for sequence, name in zip(sequences, names):
        a3m.append(u">" + name + u"\n")
        a3m.append(sequence + u"\n")
    return "".join(a3m)

def _to_a3m(sequences: Sequence[str]) -> str:

    names = ["sequence %d" % i for i in range(1, len(sequences) + 1)]
    a3m = []
    for sequence, name in zip(sequences, names):
        a3m.append(u">" + name + u"\n")
        a3m.append(sequence + u"\n")
    return "".join(a3m)


async def async_turn_on(self, **kwargs) -> None:
        """Turn light on."""

        if not self.coordinator.client.use_ble_relay:
            raise HomeAssistantError(f'A PetKit BLE relay is required to control {self.wf_data.data["name"]}')
        if not self.wf_data.group_relay:
            raise HomeAssistantError(
                f'A PetKit BLE relay is required to control {self.wf_data.data["name"]}. '
                f'PetKit did not return a valid relay device. If you do have a relay device, '
                f'it may temporarily be offline.'
            )

        try:
            await self.coordinator.client.control_water_fountain(self.wf_data, W5Command.LIGHT_ON)
        except BluetoothError:
            raise PetKitBluetoothError(f'Bluetooth connection to {self.wf_data.data["name"]} failed. Please try turning on the light again.')
        else:
            self.wf_data.data['settings']['lampRingSwitch'] = 1
            self.async_write_ha_state()
            await asyncio.sleep(1)
            await self.coordinator.async_request_refresh()

async def async_turn_on(self, **kwargs) -> None:

        if not self.coordinator.client.use_ble_relay:
            raise HomeAssistantError(f'A PetKit BLE relay is required to control {self.wf_data.data["name"]}')
        if not self.wf_data.group_relay:
            raise HomeAssistantError(
                f'A PetKit BLE relay is required to control {self.wf_data.data["name"]}. '
                f'PetKit did not return a valid relay device. If you do have a relay device, '
                f'it may temporarily be offline.'
            )

        try:
            await self.coordinator.client.control_water_fountain(self.wf_data, W5Command.LIGHT_ON)
        except BluetoothError:
            raise PetKitBluetoothError(f'Bluetooth connection to {self.wf_data.data["name"]} failed. Please try turning on the light again.')
        else:
            self.wf_data.data['settings']['lampRingSwitch'] = 1
            self.async_write_ha_state()
            await asyncio.sleep(1)
            await self.coordinator.async_request_refresh()


@property
    def native_value(self) -> str:
        """Always reset to 0,0"""

        return "0,0"

@property
    def native_value(self) -> str:

        return "0,0"


def _init_branch(self,):
        """Initialize classification branch and regression branch of head."""

        fc_cls = Linear(self.embed_dims*self.bbox_size, self.cls_out_channels)
        # fc_cls = Linear(self.embed_dims, self.cls_out_channels)

        reg_branch = []
        for _ in range(self.num_reg_fcs):
            reg_branch.append(Linear(self.embed_dims, self.embed_dims))
            reg_branch.append(nn.LayerNorm(self.embed_dims))
            reg_branch.append(nn.ReLU())

        if self.discrete_output:
            reg_branch.append(nn.Linear(
                self.embed_dims, max(self.canvas_size), bias=True,))
        else:
            reg_branch.append(nn.Linear(
                self.embed_dims, self.coord_dim, bias=True,))

        reg_branch = nn.Sequential(*reg_branch)
        # add sigmoid or not

        def _get_clones(module, N):
            return nn.ModuleList([copy.deepcopy(module) for i in range(N)])

        num_pred = self.transformer.decoder.num_layers

        if self.iterative:
            fc_cls = _get_clones(fc_cls, num_pred)
            reg_branch = _get_clones(reg_branch, num_pred)
        else:
            reg_branch = nn.ModuleList(
                [reg_branch for _ in range(num_pred)])
            fc_cls = nn.ModuleList(
                [fc_cls for _ in range(num_pred)])

        self.pre_branches = nn.ModuleDict([
            ('cls', fc_cls),
            ('reg', reg_branch), ])

def _init_branch(self,):

        fc_cls = Linear(self.embed_dims*self.bbox_size, self.cls_out_channels)
        # fc_cls = Linear(self.embed_dims, self.cls_out_channels)

        reg_branch = []
        for _ in range(self.num_reg_fcs):
            reg_branch.append(Linear(self.embed_dims, self.embed_dims))
            reg_branch.append(nn.LayerNorm(self.embed_dims))
            reg_branch.append(nn.ReLU())

        if self.discrete_output:
            reg_branch.append(nn.Linear(
                self.embed_dims, max(self.canvas_size), bias=True,))
        else:
            reg_branch.append(nn.Linear(
                self.embed_dims, self.coord_dim, bias=True,))

        reg_branch = nn.Sequential(*reg_branch)
        # add sigmoid or not

        def _get_clones(module, N):
            return nn.ModuleList([copy.deepcopy(module) for i in range(N)])

        num_pred = self.transformer.decoder.num_layers

        if self.iterative:
            fc_cls = _get_clones(fc_cls, num_pred)
            reg_branch = _get_clones(reg_branch, num_pred)
        else:
            reg_branch = nn.ModuleList(
                [reg_branch for _ in range(num_pred)])
            fc_cls = nn.ModuleList(
                [fc_cls for _ in range(num_pred)])

        self.pre_branches = nn.ModuleDict([
            ('cls', fc_cls),
            ('reg', reg_branch), ])


def _remove_invalid_boxes(
        self,
        detected_boxes,
        detected_scores,
        detected_class_labels,
        detected_masks=None,
    ):
        """Removes entries with invalid boxes.

    A box is invalid if either its xmax is smaller than its xmin, or its ymax
    is smaller than its ymin.

    Args:
      detected_boxes: A float numpy array of size [num_boxes, 4] containing box
        coordinates in [ymin, xmin, ymax, xmax] format.
      detected_scores: A float numpy array of size [num_boxes].
      detected_class_labels: A int32 numpy array of size [num_boxes].
      detected_masks: A uint8 numpy array of size [num_boxes, height, width].

    Returns:
      valid_detected_boxes: A float numpy array of size [num_valid_boxes, 4]
        containing box coordinates in [ymin, xmin, ymax, xmax] format.
      valid_detected_scores: A float numpy array of size [num_valid_boxes].
      valid_detected_class_labels: A int32 numpy array of size
        [num_valid_boxes].
      valid_detected_masks: A uint8 numpy array of size
        [num_valid_boxes, height, width].
    """
        valid_indices = np.logical_and(
            detected_boxes[:, 0] < detected_boxes[:, 2],
            detected_boxes[:, 1] < detected_boxes[:, 3],
        )
        detected_boxes = detected_boxes[valid_indices]
        detected_scores = detected_scores[valid_indices]
        detected_class_labels = detected_class_labels[valid_indices]
        if detected_masks is not None:
            detected_masks = detected_masks[valid_indices]
        return [
            detected_boxes,
            detected_scores,
            detected_class_labels,
            detected_masks,
        ]

def _remove_invalid_boxes(
        self,
        detected_boxes,
        detected_scores,
        detected_class_labels,
        detected_masks=None,
    ):

        valid_indices = np.logical_and(
            detected_boxes[:, 0] < detected_boxes[:, 2],
            detected_boxes[:, 1] < detected_boxes[:, 3],
        )
        detected_boxes = detected_boxes[valid_indices]
        detected_scores = detected_scores[valid_indices]
        detected_class_labels = detected_class_labels[valid_indices]
        if detected_masks is not None:
            detected_masks = detected_masks[valid_indices]
        return [
            detected_boxes,
            detected_scores,
            detected_class_labels,
            detected_masks,
        ]


def finalize(self):
        """Performs a final set of operations after logs have been saved."""

        return


def center_of_mass(mask, esp=1e-6):
    """Calculate the centroid coordinates of the mask.

    Args:
        mask (Tensor): The mask to be calculated, shape (h, w).
        esp (float): Avoid dividing by zero. Default: 1e-6.

    Returns:
        tuple[Tensor]: the coordinates of the center point of the mask.

            - center_h (Tensor): the center point of the height.
            - center_w (Tensor): the center point of the width.
    """
    h, w = mask.shape
    grid_h = torch.arange(h, device=mask.device)[:, None]
    grid_w = torch.arange(w, device=mask.device)
    normalizer = mask.sum().float().clamp(min=esp)
    center_h = (mask * grid_h).sum() / normalizer
    center_w = (mask * grid_w).sum() / normalizer
    return center_h, center_w

def center_of_mass(mask, esp=1e-6):

    h, w = mask.shape
    grid_h = torch.arange(h, device=mask.device)[:, None]
    grid_w = torch.arange(w, device=mask.device)
    normalizer = mask.sum().float().clamp(min=esp)
    center_h = (mask * grid_h).sum() / normalizer
    center_w = (mask * grid_w).sum() / normalizer
    return center_h, center_w


def _init_predictor(self):
        """Initialize predictor layers of the head."""
        self.conv_cls = nn.Conv2d(
            self.feat_channels, self.cls_out_channels, 3, padding=1)
        self.conv_reg = nn.Conv2d(self.feat_channels, 4, 3, padding=1)

def _init_predictor(self):

        self.conv_cls = nn.Conv2d(
            self.feat_channels, self.cls_out_channels, 3, padding=1)
        self.conv_reg = nn.Conv2d(self.feat_channels, 4, 3, padding=1)


def cty_lookup(self, callsign: str) -> list:
        """Lookup callsign in cty.dat file.

        Parameters
        ----------
        callsign : str
        callsign to lookup

        Returns
        -------
        return : list
        list of dicts containing the callsign and the station.
        """
        callsign = callsign.upper()
        for count in reversed(range(len(callsign))):
            searchitem = callsign[: count + 1]
            result = {
                key: val for key, val in self.ctyfile.items() if key == searchitem
            }
            if not result:
                continue
            if result.get(searchitem).get("exact_match"):
                if searchitem == callsign:
                    return result
                continue
            return result

def cty_lookup(self, callsign: str) -> list:

        callsign = callsign.upper()
        for count in reversed(range(len(callsign))):
            searchitem = callsign[: count + 1]
            result = {
                key: val for key, val in self.ctyfile.items() if key == searchitem
            }
            if not result:
                continue
            if result.get(searchitem).get("exact_match"):
                if searchitem == callsign:
                    return result
                continue
            return result


def change_mode(self, mode: str, intended_freq=None) -> None:
        """
        Change mode to given mode.
        Send the new mode to the rig control.
        Set the band indicator.
        Set the window title.
        Clear the inputs.
        Read the CW macros.

        Parameters
        ----------
        mode : str
        Mode to change to.

        Returns
        -------
        None
        """
        if mode in ("CW", "CW-U", "CW-L", "CWR"):
            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.rig_control.last_cw_mode)
                if self.pref.get("cwtype") == 3 and self.rig_control is not None:
                    if self.rig_control.interface == "flrig":
                        self.cwspeed_spinbox_changed()
                        self.rig_control.cat.set_flrig_cw_send(True)
            else:
                self.setmode("CW")
                self.radio_state["mode"] = "CW"
                band = getband(str(self.radio_state.get("vfoa", "0.0")))
                self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()
            return
        if mode in (
            "DIGI-U",
            "DIGI-L",
            "RTTY",
            "RTTY-R",
            "LSB-D",
            "USB-D",
            "AM-D",
            "FM-D",
        ):
            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.rig_control.last_data_mode)
            else:
                self.radio_state["mode"] = "RTTY"
            self.setmode("RTTY")
            band = getband(str(self.radio_state.get("vfoa", "0.0")))
            self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()
            return
        if mode == "SSB":
            if intended_freq:
                freq = intended_freq
            else:
                freq = int(self.radio_state.get("vfoa", 0))

            if freq > 10000000:
                self.radio_state["mode"] = "USB"
            else:
                self.radio_state["mode"] = "LSB"

            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.radio_state.get("mode"))
            else:
                self.setmode("SSB")
                band = getband(str(self.radio_state.get("vfoa", "0.0")))
                self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()

def change_mode(self, mode: str, intended_freq=None) -> None:

        if mode in ("CW", "CW-U", "CW-L", "CWR"):
            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.rig_control.last_cw_mode)
                if self.pref.get("cwtype") == 3 and self.rig_control is not None:
                    if self.rig_control.interface == "flrig":
                        self.cwspeed_spinbox_changed()
                        self.rig_control.cat.set_flrig_cw_send(True)
            else:
                self.setmode("CW")
                self.radio_state["mode"] = "CW"
                band = getband(str(self.radio_state.get("vfoa", "0.0")))
                self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()
            return
        if mode in (
            "DIGI-U",
            "DIGI-L",
            "RTTY",
            "RTTY-R",
            "LSB-D",
            "USB-D",
            "AM-D",
            "FM-D",
        ):
            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.rig_control.last_data_mode)
            else:
                self.radio_state["mode"] = "RTTY"
            self.setmode("RTTY")
            band = getband(str(self.radio_state.get("vfoa", "0.0")))
            self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()
            return
        if mode == "SSB":
            if intended_freq:
                freq = intended_freq
            else:
                freq = int(self.radio_state.get("vfoa", 0))

            if freq > 10000000:
                self.radio_state["mode"] = "USB"
            else:
                self.radio_state["mode"] = "LSB"

            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.radio_state.get("mode"))
            else:
                self.setmode("SSB")
                band = getband(str(self.radio_state.get("vfoa", "0.0")))
                self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()


def preprocess(
    img: np.ndarray, out_bbox, input_size: Tuple[int, int] = (192, 256)
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """Do preprocessing for DWPose model inference.

    Args:
        img (np.ndarray): Input image in shape.
        input_size (tuple): Input image size in shape (w, h).

    Returns:
        tuple:
        - resized_img (np.ndarray): Preprocessed image.
        - center (np.ndarray): Center of image.
        - scale (np.ndarray): Scale of image.
    """
    # get shape of image
    img_shape = img.shape[:2]
    out_img, out_center, out_scale = [], [], []
    if len(out_bbox) == 0:
        out_bbox = [[0, 0, img_shape[1], img_shape[0]]]
    for i in range(len(out_bbox)):
        x0 = out_bbox[i][0]
        y0 = out_bbox[i][1]
        x1 = out_bbox[i][2]
        y1 = out_bbox[i][3]
        bbox = np.array([x0, y0, x1, y1])

        # get center and scale
        center, scale = bbox_xyxy2cs(bbox, padding=1.25)

        # do affine transformation
        resized_img, scale = top_down_affine(input_size, scale, center, img)

        # normalize image
        mean = np.array([123.675, 116.28, 103.53])
        std = np.array([58.395, 57.12, 57.375])
        resized_img = (resized_img - mean) / std

        out_img.append(resized_img)
        out_center.append(center)
        out_scale.append(scale)

    return out_img, out_center, out_scale

def preprocess(
    img: np.ndarray, out_bbox, input_size: Tuple[int, int] = (192, 256)
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:

    # get shape of image
    img_shape = img.shape[:2]
    out_img, out_center, out_scale = [], [], []
    if len(out_bbox) == 0:
        out_bbox = [[0, 0, img_shape[1], img_shape[0]]]
    for i in range(len(out_bbox)):
        x0 = out_bbox[i][0]
        y0 = out_bbox[i][1]
        x1 = out_bbox[i][2]
        y1 = out_bbox[i][3]
        bbox = np.array([x0, y0, x1, y1])

        # get center and scale
        center, scale = bbox_xyxy2cs(bbox, padding=1.25)

        # do affine transformation
        resized_img, scale = top_down_affine(input_size, scale, center, img)

        # normalize image
        mean = np.array([123.675, 116.28, 103.53])
        std = np.array([58.395, 57.12, 57.375])
        resized_img = (resized_img - mean) / std

        out_img.append(resized_img)
        out_center.append(center)
        out_scale.append(scale)

    return out_img, out_center, out_scale


def __init__(self):
        """
        Init method.
        """
        super().__init__()

def __init__(self):

        super().__init__()


def forward(self, coeffs):
        """
        Args:
            coeffs (yl, yh): tuple of lowpass and bandpass coefficients, should
              match the format returned by DWT1DForward.

        Returns:
            Reconstructed input of shape :math:`(N, C_{in}, L_{in})`

        Note:
            Can have None for any of the highpass scales and will treat the
            values as zeros (not in an efficient way though).
        """
        x0, highs = coeffs
        assert x0.ndim == 3, "Can only handle 3d inputs (N, C, L)"
        mode = mode_to_int(self.mode)
        # Do a multilevel inverse transform
        for x1 in highs[::-1]:
            if x1 is None:
                x1 = torch.zeros_like(x0)

            # 'Unpad' added signal
            if x0.shape[-1] > x1.shape[-1]:
                x0 = x0[..., :-1]
            x0 = SFB1D.apply(x0, x1, self.g0, self.g1, mode, self.use_amp)
        return x0

def forward(self, coeffs):

        x0, highs = coeffs
        assert x0.ndim == 3, "Can only handle 3d inputs (N, C, L)"
        mode = mode_to_int(self.mode)
        # Do a multilevel inverse transform
        for x1 in highs[::-1]:
            if x1 is None:
                x1 = torch.zeros_like(x0)

            # 'Unpad' added signal
            if x0.shape[-1] > x1.shape[-1]:
                x0 = x0[..., :-1]
            x0 = SFB1D.apply(x0, x1, self.g0, self.g1, mode, self.use_amp)
        return x0


def get_auth_args():
    """
    Generates a parser which is used to get all of the authentication information
    """
    parser = ArgumentParser(
        description='TikTok Auth is a program which can log you into multiple accounts sequentially'
    )

    # authentication arguments
    parser.add_argument('-o', '--output', default='tmp',
                        help='The output folder to save the cookies to')
    parser.add_argument('-i', '--input', help='A csv file with username and password')
    # parser.add_argument('-h', '--header', default=True,
    # help='The header of the csv file which contains the username and password')
    parser.add_argument('-u', '--username', help='Your TikTok email / username')
    parser.add_argument('-p', '--password', help='Your TikTok password')

    return parser.parse_args()

def get_auth_args():

    parser = ArgumentParser(
        description='TikTok Auth is a program which can log you into multiple accounts sequentially'
    )

    # authentication arguments
    parser.add_argument('-o', '--output', default='tmp',
                        help='The output folder to save the cookies to')
    parser.add_argument('-i', '--input', help='A csv file with username and password')
    # parser.add_argument('-h', '--header', default=True,
    # help='The header of the csv file which contains the username and password')
    parser.add_argument('-u', '--username', help='Your TikTok email / username')
    parser.add_argument('-p', '--password', help='Your TikTok password')

    return parser.parse_args()


def get_transfer_statistics(self, data=None):
        """
        查询转移历史统计数据
        """
        MovieChartLabels = []
        MovieNums = []
        TvChartData = {}
        TvNums = []
        AnimeNums = []
        for statistic in self.dbhelper.get_transfer_statistics():
            if statistic[0] == "电影":
                MovieChartLabels.append(statistic[1])
                MovieNums.append(statistic[2])
            else:
                if not TvChartData.get(statistic[1]):
                    TvChartData[statistic[1]] = {"tv": 0, "anime": 0}
                if statistic[0] == "电视剧":
                    TvChartData[statistic[1]]["tv"] += statistic[2]
                elif statistic[0] == "动漫":
                    TvChartData[statistic[1]]["anime"] += statistic[2]
        TvChartLabels = list(TvChartData)
        for tv_data in TvChartData.values():
            TvNums.append(tv_data.get("tv"))
            AnimeNums.append(tv_data.get("anime"))

        return {
            "code": 0,
            "MovieChartLabels": MovieChartLabels,
            "MovieNums": MovieNums,
            "TvChartLabels": TvChartLabels,
            "TvNums": TvNums,
            "AnimeNums": AnimeNums
        }

"""
        查询转移历史统计数据
        """

def get_transfer_statistics(self, data=None):

        MovieChartLabels = []
        MovieNums = []
        TvChartData = {}
        TvNums = []
        AnimeNums = []
        for statistic in self.dbhelper.get_transfer_statistics():
            if statistic[0] == "电影":
                MovieChartLabels.append(statistic[1])
                MovieNums.append(statistic[2])
            else:
                if not TvChartData.get(statistic[1]):
                    TvChartData[statistic[1]] = {"tv": 0, "anime": 0}
                if statistic[0] == "电视剧":
                    TvChartData[statistic[1]]["tv"] += statistic[2]
                elif statistic[0] == "动漫":
                    TvChartData[statistic[1]]["anime"] += statistic[2]
        TvChartLabels = list(TvChartData)
        for tv_data in TvChartData.values():
            TvNums.append(tv_data.get("tv"))
            AnimeNums.append(tv_data.get("anime"))

        return {
            "code": 0,
            "MovieChartLabels": MovieChartLabels,
            "MovieNums": MovieNums,
            "TvChartLabels": TvChartLabels,
            "TvNums": TvNums,
            "AnimeNums": AnimeNums
        }


@filterrule.doc(parser=parser)
    def post(self):
        """
        新增/修改规则
        """
        return WebAction().api_action(cmd='add_filterrule', data=self.parser.parse_args())

@filterrule.doc(parser=parser)
    def post(self):

        return WebAction().api_action(cmd='add_filterrule', data=self.parser.parse_args())


@staticmethod
    def is_luba1(device_name: str, product_key: str = ""):
        """Check if the given device is of type LUBA.

        This function determines if the device specified by 'device_name' is of
        type LUBA. If 'product_key' is provided, it is used to further identify
        the device type.

        Args:
            device_name (str): The name of the device.
            product_key (str?): The product key associated with the device. Defaults to "".

        Returns:
            bool: True if the device is of type LUBA, False otherwise.

        """

        if not product_key:
            device_type = DeviceType.value_of_str(device_name)
        else:
            device_type = DeviceType.value_of_str(device_name, product_key)

        return device_type.get_value() == DeviceType.LUBA.get_value()

@staticmethod
    def is_luba1(device_name: str, product_key: str = ""):

        if not product_key:
            device_type = DeviceType.value_of_str(device_name)
        else:
            device_type = DeviceType.value_of_str(device_name, product_key)

        return device_type.get_value() == DeviceType.LUBA.get_value()


def update(oids, hids, dists, indices, events, m):
    """
        tracks : my results of shape {tr_id: {'id', 'im_index', 'max_iou', 'bbox'}
        num_frames : number of frames
    """
    import pandas as pd
    asso = dict()
    hypo = dict()
    cols = ['Type', 'id', 'frame', 'tr_id', 'iou', 'w', 'h']
    events = pd.DataFrame(columns=cols)
    for i in range(num_frames):
        for tr_id, tr in self.tracks.items():
            for t in tr:
                if t['im_index'] == i:
                    if t['id'] in asso.keys():
                        h_o = asso[t['id']]
                        if tr_id == h_o:
                            TYPE = 'match'
                        else:
                            if h_o in hypo.keys():
                                TYPE = 'switch'
                            else:
                                TYPE = 'ascend'
                    elif tr_id == -1:
                        TYPE = 'fp'
                    elif tr_id in hypo.keys():
                        if t['id'] not in asso.keys():
                            TYPE = 'migrate'
                        elif hypo[tr_id] != t['id']:
                            TYPE = 'transfer'
                    df = pd.DataFrame([[TYPE, t['id'], i, tr_id, t['iou'], t['bbox']
                                      [2]-t['bbox'][0], t['bbox'][3]-t['bbox'][1]]], columns=cols)

    #self.dirty_events = True
    oids = np.asarray(oids)
    oids_masked = np.zeros_like(oids, dtype=np.bool)
    hids = np.asarray(hids)
    hids_masked = np.zeros_like(hids, dtype=np.bool)
    dists = np.atleast_2d(dists).astype(float).reshape(
        oids.shape[0], hids.shape[0]).copy()

    if frameid is None:
        assert self.auto_id, 'auto-id is not enabled'
        if len(self._indices['FrameId']) > 0:
            frameid = self._indices['FrameId'][-1] + 1
        else:
            frameid = 0
    else:
        assert not self.auto_id, 'Cannot provide frame id when auto-id is enabled'

    eid = itertools.count()

    # 0. Record raw events

    no = len(oids)
    nh = len(hids)

    # Add a RAW event simply to ensure the frame is counted.
    indices.append(frameid, next(eid))
    events.append('RAW', np.nan, np.nan, np.nan)

    # There must be at least one RAW event per object and hypothesis.
    # Record all finite distances as RAW events.
    valid_i, valid_j = np.where(np.isfinite(dists))
    valid_dists = dists[valid_i, valid_j]
    for i, j, dist_ij in zip(valid_i, valid_j, valid_dists):
        indices.append(frameid, next(eid))
        events.append('RAW', oids[i], hids[j], dist_ij)
    # Add a RAW event for objects and hypotheses that were present but did
    # not overlap with anything.
    used_i = np.unique(valid_i)
    used_j = np.unique(valid_j)
    unused_i = np.setdiff1d(np.arange(no), used_i)
    unused_j = np.setdiff1d(np.arange(nh), used_j)
    for oid in oids[unused_i]:
        indices.append(frameid, next(eid))
        events.append('RAW', oid, np.nan, np.nan)
    for hid in hids[unused_j]:
        indices.append(frameid, next(eid))
        events.append('RAW', np.nan, hid, np.nan)

    if oids.size * hids.size > 0:
        # 1. Try to re-establish tracks from previous correspondences
        for i in range(oids.shape[0]):
            # No need to check oids_masked[i] here.
            if oids[i] not in self.m:
                continue

            hprev = self.m[oids[i]]
            j, = np.where(~hids_masked & (hids == hprev))
            if j.shape[0] == 0:
                continue
            j = j[0]

            if np.isfinite(dists[i, j]):
                o = oids[i]
                h = hids[j]
                oids_masked[i] = True
                hids_masked[j] = True
                self.m[oids[i]] = hids[j]

                indices.append(frameid, next(eid))
                events.append('MATCH', oids[i], hids[j], dists[i, j])
                self.last_match[o] = frameid
                self.hypHistory[h] = frameid

        # 2. Try to remaining objects/hypotheses
        dists[oids_masked, :] = np.nan
        dists[:, hids_masked] = np.nan

        rids, cids = linear_sum_assignment(dists)

        for i, j in zip(rids, cids):
            if not np.isfinite(dists[i, j]):
                continue

            o = oids[i]
            h = hids[j]
            is_switch = (o in self.m and
                         self.m[o] != h and
                         abs(frameid - self.last_occurrence[o]) <= self.max_switch_time)
            cat1 = 'SWITCH' if is_switch else 'MATCH'
            if cat1 == 'SWITCH':
                if h not in self.hypHistory:
                    subcat = 'ASCEND'
                    indices.append(frameid, next(eid))
                    events.append(subcat, oids[i], hids[j], dists[i, j])
            # ignore the last condition temporarily
            is_transfer = (h in self.res_m and
                           self.res_m[h] != o)
            # is_transfer = (h in self.res_m and
            #                self.res_m[h] != o and
            #                abs(frameid - self.last_occurrence[o]) <= self.max_switch_time)
            cat2 = 'TRANSFER' if is_transfer else 'MATCH'
            if cat2 == 'TRANSFER':
                if o not in self.last_match:
                    subcat = 'MIGRATE'
                    indices.append(frameid, next(eid))
                    events.append(subcat, oids[i], hids[j], dists[i, j])
                indices.append(frameid, next(eid))
                events.append(cat2, oids[i], hids[j], dists[i, j])
            if vf != '' and (cat1 != 'MATCH' or cat2 != 'MATCH'):
                if cat1 == 'SWITCH':
                    vf.write('%s %d %d %d %d %d\n' % (
                        subcat[:2], o, self.last_match[o], self.m[o], frameid, h))
                if cat2 == 'TRANSFER':
                    vf.write('%s %d %d %d %d %d\n' % (
                        subcat[:2], h, self.hypHistory[h], self.res_m[h], frameid, o))
            self.hypHistory[h] = frameid
            self.last_match[o] = frameid
            indices.append(frameid, next(eid))
            events.append(cat1, oids[i], hids[j], dists[i, j])
            oids_masked[i] = True
            hids_masked[j] = True
            self.m[o] = h
            self.res_m[h] = o

    # 3. All remaining objects are missed
    for o in oids[~oids_masked]:
        indices.append(frameid, next(eid))
        events.append('MISS', o, np.nan, np.nan)
        if vf != '':
            vf.write('FN %d %d\n' % (frameid, o))

    # 4. All remaining hypotheses are false alarms
    for h in hids[~hids_masked]:
        indices.append(frameid, next(eid))
        events.append('FP', np.nan, h, np.nan)
        if vf != '':
            vf.write('FP %d %d\n' % (frameid, h))

    # 5. Update occurance state
    for o in oids:
        self.last_occurrence[o] = frameid

    return frameid

def update(oids, hids, dists, indices, events, m):

    import pandas as pd
    asso = dict()
    hypo = dict()
    cols = ['Type', 'id', 'frame', 'tr_id', 'iou', 'w', 'h']
    events = pd.DataFrame(columns=cols)
    for i in range(num_frames):
        for tr_id, tr in self.tracks.items():
            for t in tr:
                if t['im_index'] == i:
                    if t['id'] in asso.keys():
                        h_o = asso[t['id']]
                        if tr_id == h_o:
                            TYPE = 'match'
                        else:
                            if h_o in hypo.keys():
                                TYPE = 'switch'
                            else:
                                TYPE = 'ascend'
                    elif tr_id == -1:
                        TYPE = 'fp'
                    elif tr_id in hypo.keys():
                        if t['id'] not in asso.keys():
                            TYPE = 'migrate'
                        elif hypo[tr_id] != t['id']:
                            TYPE = 'transfer'
                    df = pd.DataFrame([[TYPE, t['id'], i, tr_id, t['iou'], t['bbox']
                                      [2]-t['bbox'][0], t['bbox'][3]-t['bbox'][1]]], columns=cols)

    #self.dirty_events = True
    oids = np.asarray(oids)
    oids_masked = np.zeros_like(oids, dtype=np.bool)
    hids = np.asarray(hids)
    hids_masked = np.zeros_like(hids, dtype=np.bool)
    dists = np.atleast_2d(dists).astype(float).reshape(
        oids.shape[0], hids.shape[0]).copy()

    if frameid is None:
        assert self.auto_id, 'auto-id is not enabled'
        if len(self._indices['FrameId']) > 0:
            frameid = self._indices['FrameId'][-1] + 1
        else:
            frameid = 0
    else:
        assert not self.auto_id, 'Cannot provide frame id when auto-id is enabled'

    eid = itertools.count()

    # 0. Record raw events

    no = len(oids)
    nh = len(hids)

    # Add a RAW event simply to ensure the frame is counted.
    indices.append(frameid, next(eid))
    events.append('RAW', np.nan, np.nan, np.nan)

    # There must be at least one RAW event per object and hypothesis.
    # Record all finite distances as RAW events.
    valid_i, valid_j = np.where(np.isfinite(dists))
    valid_dists = dists[valid_i, valid_j]
    for i, j, dist_ij in zip(valid_i, valid_j, valid_dists):
        indices.append(frameid, next(eid))
        events.append('RAW', oids[i], hids[j], dist_ij)
    # Add a RAW event for objects and hypotheses that were present but did
    # not overlap with anything.
    used_i = np.unique(valid_i)
    used_j = np.unique(valid_j)
    unused_i = np.setdiff1d(np.arange(no), used_i)
    unused_j = np.setdiff1d(np.arange(nh), used_j)
    for oid in oids[unused_i]:
        indices.append(frameid, next(eid))
        events.append('RAW', oid, np.nan, np.nan)
    for hid in hids[unused_j]:
        indices.append(frameid, next(eid))
        events.append('RAW', np.nan, hid, np.nan)

    if oids.size * hids.size > 0:
        # 1. Try to re-establish tracks from previous correspondences
        for i in range(oids.shape[0]):
            # No need to check oids_masked[i] here.
            if oids[i] not in self.m:
                continue

            hprev = self.m[oids[i]]
            j, = np.where(~hids_masked & (hids == hprev))
            if j.shape[0] == 0:
                continue
            j = j[0]

            if np.isfinite(dists[i, j]):
                o = oids[i]
                h = hids[j]
                oids_masked[i] = True
                hids_masked[j] = True
                self.m[oids[i]] = hids[j]

                indices.append(frameid, next(eid))
                events.append('MATCH', oids[i], hids[j], dists[i, j])
                self.last_match[o] = frameid
                self.hypHistory[h] = frameid

        # 2. Try to remaining objects/hypotheses
        dists[oids_masked, :] = np.nan
        dists[:, hids_masked] = np.nan

        rids, cids = linear_sum_assignment(dists)

        for i, j in zip(rids, cids):
            if not np.isfinite(dists[i, j]):
                continue

            o = oids[i]
            h = hids[j]
            is_switch = (o in self.m and
                         self.m[o] != h and
                         abs(frameid - self.last_occurrence[o]) <= self.max_switch_time)
            cat1 = 'SWITCH' if is_switch else 'MATCH'
            if cat1 == 'SWITCH':
                if h not in self.hypHistory:
                    subcat = 'ASCEND'
                    indices.append(frameid, next(eid))
                    events.append(subcat, oids[i], hids[j], dists[i, j])
            # ignore the last condition temporarily
            is_transfer = (h in self.res_m and
                           self.res_m[h] != o)
            # is_transfer = (h in self.res_m and
            #                self.res_m[h] != o and
            #                abs(frameid - self.last_occurrence[o]) <= self.max_switch_time)
            cat2 = 'TRANSFER' if is_transfer else 'MATCH'
            if cat2 == 'TRANSFER':
                if o not in self.last_match:
                    subcat = 'MIGRATE'
                    indices.append(frameid, next(eid))
                    events.append(subcat, oids[i], hids[j], dists[i, j])
                indices.append(frameid, next(eid))
                events.append(cat2, oids[i], hids[j], dists[i, j])
            if vf != '' and (cat1 != 'MATCH' or cat2 != 'MATCH'):
                if cat1 == 'SWITCH':
                    vf.write('%s %d %d %d %d %d\n' % (
                        subcat[:2], o, self.last_match[o], self.m[o], frameid, h))
                if cat2 == 'TRANSFER':
                    vf.write('%s %d %d %d %d %d\n' % (
                        subcat[:2], h, self.hypHistory[h], self.res_m[h], frameid, o))
            self.hypHistory[h] = frameid
            self.last_match[o] = frameid
            indices.append(frameid, next(eid))
            events.append(cat1, oids[i], hids[j], dists[i, j])
            oids_masked[i] = True
            hids_masked[j] = True
            self.m[o] = h
            self.res_m[h] = o

    # 3. All remaining objects are missed
    for o in oids[~oids_masked]:
        indices.append(frameid, next(eid))
        events.append('MISS', o, np.nan, np.nan)
        if vf != '':
            vf.write('FN %d %d\n' % (frameid, o))

    # 4. All remaining hypotheses are false alarms
    for h in hids[~hids_masked]:
        indices.append(frameid, next(eid))
        events.append('FP', np.nan, h, np.nan)
        if vf != '':
            vf.write('FP %d %d\n' % (frameid, h))

    # 5. Update occurance state
    for o in oids:
        self.last_occurrence[o] = frameid

    return frameid


def checkpoint_filter_fn(state_dict, model):
    """ convert patch embedding weight from manual patchify + linear proj to conv"""
    out_dict = {}
    if 'model' in state_dict:
        # For deit models
        state_dict = state_dict['model']
    for k, v in state_dict.items():
        if 'patch_embed.proj.weight' in k and len(v.shape) < 4:
            # For old models that I trained prior to conv based patchification
            O, I, H, W = model.patch_embed.proj.weight.shape
            v = v.reshape(O, -1, H, W)
        elif k == 'pos_embed' and v.shape != model.pos_embed.shape:
            # To resize pos embedding when using model at different size from pretrained weights
            v = resize_pos_embed(v, model.pos_embed, getattr(model, 'num_tokens', 1),
                                                model.patch_embed.grid_size)
        out_dict[k] = v
    return out_dict

def checkpoint_filter_fn(state_dict, model):

    out_dict = {}
    if 'model' in state_dict:
        # For deit models
        state_dict = state_dict['model']
    for k, v in state_dict.items():
        if 'patch_embed.proj.weight' in k and len(v.shape) < 4:
            # For old models that I trained prior to conv based patchification
            O, I, H, W = model.patch_embed.proj.weight.shape
            v = v.reshape(O, -1, H, W)
        elif k == 'pos_embed' and v.shape != model.pos_embed.shape:
            # To resize pos embedding when using model at different size from pretrained weights
            v = resize_pos_embed(v, model.pos_embed, getattr(model, 'num_tokens', 1),
                                                model.patch_embed.grid_size)
        out_dict[k] = v
    return out_dict


def setup_filters(self, filter_cls, filter_args):
        "Initializes the explicit and implicit filters"
        assert self.order >= 2, f'Order must be at least 2, (got {self.order})'
        total_width = self.d_model * self.inner_factor * (self.order + 1)

        self.short_filter = nn.Conv1d(
            in_channels=total_width,
            out_channels=total_width,
            kernel_size=self.short_filter_order,
            groups=total_width,
            padding=self.short_filter_order - 1
        )

        filter_cls = instantiate(registry.layer, filter_cls, partial=True)

        self.filter_fn = filter_cls(
            self.head_dim * self.inner_factor * (self.order - 1),
            order=self.filter_order,
            seq_len=self.l_max,
            channels=1,
            dropout=self.filter_dropout,
            **filter_args
        )
        if self.jit_filter: self.filter_fn = torch.jit.script(self.filter_fn, self.L)

def setup_filters(self, filter_cls, filter_args):

        assert self.order >= 2, f'Order must be at least 2, (got {self.order})'
        total_width = self.d_model * self.inner_factor * (self.order + 1)

        self.short_filter = nn.Conv1d(
            in_channels=total_width,
            out_channels=total_width,
            kernel_size=self.short_filter_order,
            groups=total_width,
            padding=self.short_filter_order - 1
        )

        filter_cls = instantiate(registry.layer, filter_cls, partial=True)

        self.filter_fn = filter_cls(
            self.head_dim * self.inner_factor * (self.order - 1),
            order=self.filter_order,
            seq_len=self.l_max,
            channels=1,
            dropout=self.filter_dropout,
            **filter_args
        )
        if self.jit_filter: self.filter_fn = torch.jit.script(self.filter_fn, self.L)


@mmcv.jit(derivate=True, coderize=True)
def custom_weight_dir_reduce_loss(loss, weight=None, reduction='mean', avg_factor=None):
    """Apply element-wise weight and reduce loss.

    Args:
        loss (Tensor): num_sample, num_dir
        weight (Tensor): Element-wise weights.
        reduction (str): Same as built-in losses of PyTorch.
        avg_factor (float): Average factor when computing the mean of losses.

    Returns:
        Tensor: Processed loss values.
    """
    # if weight is specified, apply element-wise weight
    if weight is not None:
        loss = loss * weight

    # if avg_factor is not specified, just reduce the loss
    if avg_factor is None:
        raise ValueError('avg_factor should not be none for OrderedPtsL1Loss')
        # loss = reduce_loss(loss, reduction)
    else:
        # if reduction is mean, then average the loss by avg_factor
        if reduction == 'mean':
            # import pdb;pdb.set_trace()
            # loss = loss.permute(1,0,2,3).contiguous()
            loss = loss.sum()
            loss = loss / avg_factor
        # if reduction is 'none', then do nothing, otherwise raise an error
        elif reduction != 'none':
            raise ValueError('avg_factor can not be used with reduction="sum"')
    return loss

@mmcv.jit(derivate=True, coderize=True)
def custom_weight_dir_reduce_loss(loss, weight=None, reduction='mean', avg_factor=None):

    # if weight is specified, apply element-wise weight
    if weight is not None:
        loss = loss * weight

    # if avg_factor is not specified, just reduce the loss
    if avg_factor is None:
        raise ValueError('avg_factor should not be none for OrderedPtsL1Loss')
        # loss = reduce_loss(loss, reduction)
    else:
        # if reduction is mean, then average the loss by avg_factor
        if reduction == 'mean':
            # import pdb;pdb.set_trace()
            # loss = loss.permute(1,0,2,3).contiguous()
            loss = loss.sum()
            loss = loss / avg_factor
        # if reduction is 'none', then do nothing, otherwise raise an error
        elif reduction != 'none':
            raise ValueError('avg_factor can not be used with reduction="sum"')
    return loss


def add_model_config(path):
    """add model config path or file and update registry"""
    if not isinstance(path, Path):
        path = Path(path)
    _MODEL_CONFIG_PATHS.append(path)
    _rescan_model_configs()

def add_model_config(path):

    if not isinstance(path, Path):
        path = Path(path)
    _MODEL_CONFIG_PATHS.append(path)
    _rescan_model_configs()


@staticmethod
    def set_config_value(cfg, cfg_key, cfg_value):
        """
        根据Key设置配置值
        """
        # 密码
        if cfg_key == "app.login_password":
            if cfg_value and not cfg_value.startswith("[hash]"):
                cfg['app']['login_password'] = "[hash]%s" % generate_password_hash(
                    cfg_value)
            else:
                cfg['app']['login_password'] = cfg_value or "password"
            return cfg
        # 代理
        if cfg_key == "app.proxies":
            if cfg_value:
                if not cfg_value.startswith("http") and not cfg_value.startswith("sock"):
                    cfg['app']['proxies'] = {
                        "https": "http://%s" % cfg_value, "http": "http://%s" % cfg_value}
                else:
                    cfg['app']['proxies'] = {"https": "%s" %
                                             cfg_value, "http": "%s" % cfg_value}
            else:
                cfg['app']['proxies'] = {"https": None, "http": None}
            return cfg
        # 豆瓣用户列表
        if cfg_key == "douban.users":
            vals = cfg_value.split(",")
            cfg['douban']['users'] = vals
            return cfg
        # 索引器
        if cfg_key == "jackett.indexers":
            vals = cfg_value.split("\n")
            cfg['jackett']['indexers'] = vals
            return cfg
        # 最大支持三层赋值
        keys = cfg_key.split(".")
        if keys:
            if len(keys) == 1:
                cfg[keys[0]] = cfg_value
            elif len(keys) == 2:
                if not cfg.get(keys[0]):
                    cfg[keys[0]] = {}
                cfg[keys[0]][keys[1]] = cfg_value
            elif len(keys) == 3:
                if cfg.get(keys[0]):
                    if not cfg[keys[0]].get(keys[1]) or isinstance(cfg[keys[0]][keys[1]], str):
                        cfg[keys[0]][keys[1]] = {}
                    cfg[keys[0]][keys[1]][keys[2]] = cfg_value
                else:
                    cfg[keys[0]] = {}
                    cfg[keys[0]][keys[1]] = {}
                    cfg[keys[0]][keys[1]][keys[2]] = cfg_value

        return cfg

@staticmethod
    def set_config_value(cfg, cfg_key, cfg_value):

        # 密码
        if cfg_key == "app.login_password":
            if cfg_value and not cfg_value.startswith("[hash]"):
                cfg['app']['login_password'] = "[hash]%s" % generate_password_hash(
                    cfg_value)
            else:
                cfg['app']['login_password'] = cfg_value or "password"
            return cfg
        # 代理
        if cfg_key == "app.proxies":
            if cfg_value:
                if not cfg_value.startswith("http") and not cfg_value.startswith("sock"):
                    cfg['app']['proxies'] = {
                        "https": "http://%s" % cfg_value, "http": "http://%s" % cfg_value}
                else:
                    cfg['app']['proxies'] = {"https": "%s" %
                                             cfg_value, "http": "%s" % cfg_value}
            else:
                cfg['app']['proxies'] = {"https": None, "http": None}
            return cfg
        # 豆瓣用户列表
        if cfg_key == "douban.users":
            vals = cfg_value.split(",")
            cfg['douban']['users'] = vals
            return cfg
        # 索引器
        if cfg_key == "jackett.indexers":
            vals = cfg_value.split("\n")
            cfg['jackett']['indexers'] = vals
            return cfg
        # 最大支持三层赋值
        keys = cfg_key.split(".")
        if keys:
            if len(keys) == 1:
                cfg[keys[0]] = cfg_value
            elif len(keys) == 2:
                if not cfg.get(keys[0]):
                    cfg[keys[0]] = {}
                cfg[keys[0]][keys[1]] = cfg_value
            elif len(keys) == 3:
                if cfg.get(keys[0]):
                    if not cfg[keys[0]].get(keys[1]) or isinstance(cfg[keys[0]][keys[1]], str):
                        cfg[keys[0]][keys[1]] = {}
                    cfg[keys[0]][keys[1]][keys[2]] = cfg_value
                else:
                    cfg[keys[0]] = {}
                    cfg[keys[0]][keys[1]] = {}
                    cfg[keys[0]][keys[1]][keys[2]] = cfg_value

        return cfg


async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]":
        """Return POST parameters."""
        if self._post is not None:
            return self._post
        if self._method not in self.POST_METHODS:
            self._post = MultiDictProxy(MultiDict())
            return self._post

        content_type = self.content_type
        if content_type not in (
            "",
            "application/x-www-form-urlencoded",
            "multipart/form-data",
        ):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()

        if content_type == "multipart/form-data":
            multipart = await self.multipart()
            max_size = self._client_max_size

            field = await multipart.next()
            while field is not None:
                size = 0
                field_ct = field.headers.get(hdrs.CONTENT_TYPE)

                if isinstance(field, BodyPartReader):
                    assert field.name is not None

                    # Note that according to RFC 7578, the Content-Type header
                    # is optional, even for files, so we can't assume it's
                    # present.
                    # https://tools.ietf.org/html/rfc7578#section-4.4
                    if field.filename:
                        # store file in temp file
                        tmp = tempfile.TemporaryFile()
                        chunk = await field.read_chunk(size=2**16)
                        while chunk:
                            chunk = field.decode(chunk)
                            tmp.write(chunk)
                            size += len(chunk)
                            if 0 < max_size < size:
                                tmp.close()
                                raise HTTPRequestEntityTooLarge(
                                    max_size=max_size, actual_size=size
                                )
                            chunk = await field.read_chunk(size=2**16)
                        tmp.seek(0)

                        if field_ct is None:
                            field_ct = "application/octet-stream"

                        ff = FileField(
                            field.name,
                            field.filename,
                            cast(io.BufferedReader, tmp),
                            field_ct,
                            field.headers,
                        )
                        out.add(field.name, ff)
                    else:
                        # deal with ordinary data
                        value = await field.read(decode=True)
                        if field_ct is None or field_ct.startswith("text/"):
                            charset = field.get_charset(default="utf-8")
                            out.add(field.name, value.decode(charset))
                        else:
                            out.add(field.name, value)
                        size += len(value)
                        if 0 < max_size < size:
                            raise HTTPRequestEntityTooLarge(
                                max_size=max_size, actual_size=size
                            )
                else:
                    raise ValueError(
                        "To decode nested multipart you need " "to use custom reader",
                    )

                field = await multipart.next()
        else:
            data = await self.read()
            if data:
                charset = self.charset or "utf-8"
                out.extend(
                    parse_qsl(
                        data.rstrip().decode(charset),
                        keep_blank_values=True,
                        encoding=charset,
                    )
                )

        self._post = MultiDictProxy(out)
        return self._post

async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]":

        if self._post is not None:
            return self._post
        if self._method not in self.POST_METHODS:
            self._post = MultiDictProxy(MultiDict())
            return self._post

        content_type = self.content_type
        if content_type not in (
            "",
            "application/x-www-form-urlencoded",
            "multipart/form-data",
        ):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()

        if content_type == "multipart/form-data":
            multipart = await self.multipart()
            max_size = self._client_max_size

            field = await multipart.next()
            while field is not None:
                size = 0
                field_ct = field.headers.get(hdrs.CONTENT_TYPE)

                if isinstance(field, BodyPartReader):
                    assert field.name is not None

                    # Note that according to RFC 7578, the Content-Type header
                    # is optional, even for files, so we can't assume it's
                    # present.
                    # https://tools.ietf.org/html/rfc7578#section-4.4
                    if field.filename:
                        # store file in temp file
                        tmp = tempfile.TemporaryFile()
                        chunk = await field.read_chunk(size=2**16)
                        while chunk:
                            chunk = field.decode(chunk)
                            tmp.write(chunk)
                            size += len(chunk)
                            if 0 < max_size < size:
                                tmp.close()
                                raise HTTPRequestEntityTooLarge(
                                    max_size=max_size, actual_size=size
                                )
                            chunk = await field.read_chunk(size=2**16)
                        tmp.seek(0)

                        if field_ct is None:
                            field_ct = "application/octet-stream"

                        ff = FileField(
                            field.name,
                            field.filename,
                            cast(io.BufferedReader, tmp),
                            field_ct,
                            field.headers,
                        )
                        out.add(field.name, ff)
                    else:
                        # deal with ordinary data
                        value = await field.read(decode=True)
                        if field_ct is None or field_ct.startswith("text/"):
                            charset = field.get_charset(default="utf-8")
                            out.add(field.name, value.decode(charset))
                        else:
                            out.add(field.name, value)
                        size += len(value)
                        if 0 < max_size < size:
                            raise HTTPRequestEntityTooLarge(
                                max_size=max_size, actual_size=size
                            )
                else:
                    raise ValueError(
                        "To decode nested multipart you need " "to use custom reader",
                    )

                field = await multipart.next()
        else:
            data = await self.read()
            if data:
                charset = self.charset or "utf-8"
                out.extend(
                    parse_qsl(
                        data.rstrip().decode(charset),
                        keep_blank_values=True,
                        encoding=charset,
                    )
                )

        self._post = MultiDictProxy(out)
        return self._post


def add_put(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute:
        """Shortcut for add_route with method PUT."""
        return self.add_route(hdrs.METH_PUT, path, handler, **kwargs)

def add_put(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute:

        return self.add_route(hdrs.METH_PUT, path, handler, **kwargs)


def create_memory_object_stream(
    max_buffer_size: float = 0, item_type: type[T_Item] | None = None
) -> tuple[MemoryObjectSendStream[Any], MemoryObjectReceiveStream[Any]]:
    """
    Create a memory object stream.

    :param max_buffer_size: number of items held in the buffer until ``send()`` starts blocking
    :param item_type: type of item, for marking the streams with the right generic type for
        static typing (not used at run time)
    :return: a tuple of (send stream, receive stream)

    """
    if max_buffer_size != math.inf and not isinstance(max_buffer_size, int):
        raise ValueError("max_buffer_size must be either an integer or math.inf")
    if max_buffer_size < 0:
        raise ValueError("max_buffer_size cannot be negative")

    state: MemoryObjectStreamState = MemoryObjectStreamState(max_buffer_size)
    return MemoryObjectSendStream(state), MemoryObjectReceiveStream(state)

def create_memory_object_stream(
    max_buffer_size: float = 0, item_type: type[T_Item] | None = None
) -> tuple[MemoryObjectSendStream[Any], MemoryObjectReceiveStream[Any]]:

    if max_buffer_size != math.inf and not isinstance(max_buffer_size, int):
        raise ValueError("max_buffer_size must be either an integer or math.inf")
    if max_buffer_size < 0:
        raise ValueError("max_buffer_size cannot be negative")

    state: MemoryObjectStreamState = MemoryObjectStreamState(max_buffer_size)
    return MemoryObjectSendStream(state), MemoryObjectReceiveStream(state)


def _colors_to_code(self, fg_color: str, bg_color: str) -> Iterable[str]:
        """
        Return a tuple with the vt100 values  that represent this color.
        """
        # When requesting ANSI colors only, and both fg/bg color were converted
        # to ANSI, ensure that the foreground and background color are not the
        # same. (Unless they were explicitly defined to be the same color.)
        fg_ansi = ""

        def get(color: str, bg: bool) -> list[int]:
            nonlocal fg_ansi

            table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS

            if not color or self.color_depth == ColorDepth.DEPTH_1_BIT:
                return []

            # 16 ANSI colors. (Given by name.)
            elif color in table:
                return [table[color]]

            # RGB colors. (Defined as 'ffffff'.)
            else:
                try:
                    rgb = self._color_name_to_rgb(color)
                except ValueError:
                    return []

                # When only 16 colors are supported, use that.
                if self.color_depth == ColorDepth.DEPTH_4_BIT:
                    if bg:  # Background.
                        if fg_color != bg_color:
                            exclude = [fg_ansi]
                        else:
                            exclude = []
                        code, name = _16_bg_colors.get_code(rgb, exclude=exclude)
                        return [code]
                    else:  # Foreground.
                        code, name = _16_fg_colors.get_code(rgb)
                        fg_ansi = name
                        return [code]

                # True colors. (Only when this feature is enabled.)
                elif self.color_depth == ColorDepth.DEPTH_24_BIT:
                    r, g, b = rgb
                    return [(48 if bg else 38), 2, r, g, b]

                # 256 RGB colors.
                else:
                    return [(48 if bg else 38), 5, _256_colors[rgb]]

        result: list[int] = []
        result.extend(get(fg_color, False))
        result.extend(get(bg_color, True))

        return map(str, result)

def _colors_to_code(self, fg_color: str, bg_color: str) -> Iterable[str]:

        # When requesting ANSI colors only, and both fg/bg color were converted
        # to ANSI, ensure that the foreground and background color are not the
        # same. (Unless they were explicitly defined to be the same color.)
        fg_ansi = ""

        def get(color: str, bg: bool) -> list[int]:
            nonlocal fg_ansi

            table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS

            if not color or self.color_depth == ColorDepth.DEPTH_1_BIT:
                return []

            # 16 ANSI colors. (Given by name.)
            elif color in table:
                return [table[color]]

            # RGB colors. (Defined as 'ffffff'.)
            else:
                try:
                    rgb = self._color_name_to_rgb(color)
                except ValueError:
                    return []

                # When only 16 colors are supported, use that.
                if self.color_depth == ColorDepth.DEPTH_4_BIT:
                    if bg:  # Background.
                        if fg_color != bg_color:
                            exclude = [fg_ansi]
                        else:
                            exclude = []
                        code, name = _16_bg_colors.get_code(rgb, exclude=exclude)
                        return [code]
                    else:  # Foreground.
                        code, name = _16_fg_colors.get_code(rgb)
                        fg_ansi = name
                        return [code]

                # True colors. (Only when this feature is enabled.)
                elif self.color_depth == ColorDepth.DEPTH_24_BIT:
                    r, g, b = rgb
                    return [(48 if bg else 38), 2, r, g, b]

                # 256 RGB colors.
                else:
                    return [(48 if bg else 38), 5, _256_colors[rgb]]

        result: list[int] = []
        result.extend(get(fg_color, False))
        result.extend(get(bg_color, True))

        return map(str, result)


def extract_from_urllib3():
    """
    Undo monkey-patching by :func:`inject_into_urllib3`.
    """
    util.SSLContext = orig_util_SSLContext
    util.ssl_.SSLContext = orig_util_SSLContext
    util.HAS_SNI = orig_util_HAS_SNI
    util.ssl_.HAS_SNI = orig_util_HAS_SNI
    util.IS_SECURETRANSPORT = False
    util.ssl_.IS_SECURETRANSPORT = False

def extract_from_urllib3():

    util.SSLContext = orig_util_SSLContext
    util.ssl_.SSLContext = orig_util_SSLContext
    util.HAS_SNI = orig_util_HAS_SNI
    util.ssl_.HAS_SNI = orig_util_HAS_SNI
    util.IS_SECURETRANSPORT = False
    util.ssl_.IS_SECURETRANSPORT = False


@property
    def hostname(self):
        """For backwards-compatibility with urlparse. We're nice like that."""
        return self.host

@property
    def hostname(self):

        return self.host


def test_decomposition_nested(self):
        """Tests decompositions of nested controlled operations"""

        ctrl_op = C_ctrl(C_ctrl(lambda: qml.RZ(0.123, wires=0), control=1), control=2)()
        expected = [
            qml.ops.Controlled(qml.RZ(0.123, wires=0), control_wires=[1, 2]),
        ]
        assert ctrl_op.decomposition() == expected

def test_decomposition_nested(self):

        ctrl_op = C_ctrl(C_ctrl(lambda: qml.RZ(0.123, wires=0), control=1), control=2)()
        expected = [
            qml.ops.Controlled(qml.RZ(0.123, wires=0), control_wires=[1, 2]),
        ]
        assert ctrl_op.decomposition() == expected


@pytest.mark.xfail(
    reason="QJIT fails with ValueError: Eagerly computing the adjoint (lazy=False) is only supported on single operators."
)
def test_pattern_matching_optimization(backend):
    """Test pattern_matching_optimization"""

    def qnode_builder(device_name):
        """Builder"""

        ops = [qml.S(0), qml.S(0), qml.Z(0)]
        pattern = qml.tape.QuantumTape(ops)

        @partial(qml.transforms.pattern_matching_optimization, pattern_tapes=[pattern])
        @qml.qnode(qml.device(device_name, wires=5))
        def qfunc():
            qml.S(wires=0)
            qml.Z(0)
            qml.S(wires=1)
            qml.CZ(wires=[0, 1])
            qml.S(wires=1)
            qml.S(wires=2)
            qml.CZ(wires=[1, 2])
            qml.S(wires=2)
            return qml.expval(qml.X(0))

        return qfunc

    qnode_control = qnode_builder("default.qubit")
    qnode_backend = qnode_builder(backend)

    jax_jit = jax.jit(qnode_control)
    compiled = qjit(qnode_backend)

    expected = jax_jit()
    observed = compiled()
    _, expected_shape = jax.tree_util.tree_flatten(expected)
    _, observed_shape = jax.tree_util.tree_flatten(observed)

    assert np.allclose(expected, observed)
    assert expected_shape == observed_shape

@pytest.mark.xfail(
    reason="QJIT fails with ValueError: Eagerly computing the adjoint (lazy=False) is only supported on single operators."
)
def test_pattern_matching_optimization(backend):

    def qnode_builder(device_name):
        """Builder"""

        ops = [qml.S(0), qml.S(0), qml.Z(0)]
        pattern = qml.tape.QuantumTape(ops)

        @partial(qml.transforms.pattern_matching_optimization, pattern_tapes=[pattern])
        @qml.qnode(qml.device(device_name, wires=5))
        def qfunc():
            qml.S(wires=0)
            qml.Z(0)
            qml.S(wires=1)
            qml.CZ(wires=[0, 1])
            qml.S(wires=1)
            qml.S(wires=2)
            qml.CZ(wires=[1, 2])
            qml.S(wires=2)
            return qml.expval(qml.X(0))

        return qfunc

    qnode_control = qnode_builder("default.qubit")
    qnode_backend = qnode_builder(backend)

    jax_jit = jax.jit(qnode_control)
    compiled = qjit(qnode_backend)

    expected = jax_jit()
    observed = compiled()
    _, expected_shape = jax.tree_util.tree_flatten(expected)
    _, observed_shape = jax.tree_util.tree_flatten(observed)

    assert np.allclose(expected, observed)
    assert expected_shape == observed_shape


def forward(self,
                query,
                key,
                value,
                query_pos=None,
                key_pos=None,
                attn_masks=None,
                query_key_padding_mask=None,
                key_padding_mask=None,
                **kwargs):
        """Forward function for `TransformerCoder`.

        Args:
            query (Tensor): Input query with shape
                `(num_queries, bs, embed_dims)`.
            key (Tensor): The key tensor with shape
                `(num_keys, bs, embed_dims)`.
            value (Tensor): The value tensor with shape
                `(num_keys, bs, embed_dims)`.
            query_pos (Tensor): The positional encoding for `query`.
                Default: None.
            key_pos (Tensor): The positional encoding for `key`.
                Default: None.
            attn_masks (List[Tensor], optional): Each element is 2D Tensor
                which is used in calculation of corresponding attention in
                operation_order. Default: None.
            query_key_padding_mask (Tensor): ByteTensor for `query`, with
                shape [bs, num_queries]. Only used in self-attention
                Default: None.
            key_padding_mask (Tensor): ByteTensor for `query`, with
                shape [bs, num_keys]. Default: None.

        Returns:
            Tensor:  results with shape [num_queries, bs, embed_dims].
        """
        for layer in self.layers:
            query = layer(
                query,
                key,
                value,
                query_pos=query_pos,
                key_pos=key_pos,
                attn_masks=attn_masks,
                query_key_padding_mask=query_key_padding_mask,
                key_padding_mask=key_padding_mask,
                **kwargs)
        return query

def forward(self,
                query,
                key,
                value,
                query_pos=None,
                key_pos=None,
                attn_masks=None,
                query_key_padding_mask=None,
                key_padding_mask=None,
                **kwargs):

        for layer in self.layers:
            query = layer(
                query,
                key,
                value,
                query_pos=query_pos,
                key_pos=key_pos,
                attn_masks=attn_masks,
                query_key_padding_mask=query_key_padding_mask,
                key_padding_mask=key_padding_mask,
                **kwargs)
        return query


@classmethod
    def v1_from_args(
        cls, vocab_size: int, *, num_layers: int, hidden_dim: int, num_heads: int
    ) -> CausalLM:
        """Build a v1 Causal LM.

        Args:
            vocab_size: The vocabulary size.
            num_layers: The number of transformer layers.
            hidden_dim: The model hidden dimension.
            num_heads: THe number of attention heads.

        Returns:
            Initialized model.
        """
        model = CausalLM(
            decoder=Decoder(
                attention_mask=ALiBiAttentionLogitBiasLayer(num_heads),
                emb=TransformerEmbeddings(Embedding(vocab_size, embedding_dim=hidden_dim)),
                transformer=StackedTransformerLayer(
                    num_layers,
                    layer=TransformerLayer(
                        self_attention=TransformerAttentionLayer(
                            target_dim=hidden_dim,
                            source_dim=hidden_dim,
                            num_heads=num_heads,
                            structure="prenorm",
                            norm="rmsnorm",
                            qkv_linear_cls=FusedQKVLinear,
                            linear_biases=False,
                        ),
                        feed_forward=TransformerFeedForwardLayer(
                            input_dim=hidden_dim,
                            hidden_dim=round(hidden_dim * (21.0 / 8.0)),
                            activation=(
                                _torch_activation_fn("nn.silu"),
                                _torch_activation_fn("linear"),
                            ),
                            structure="prenorm",
                            norm="rmsnorm",
                            linear_biases=False,
                        ),
                    ),
                ),
                output_norm="rmsnorm",
            )
        )
        return model

@classmethod
    def v1_from_args(
        cls, vocab_size: int, *, num_layers: int, hidden_dim: int, num_heads: int
    ) -> CausalLM:

        model = CausalLM(
            decoder=Decoder(
                attention_mask=ALiBiAttentionLogitBiasLayer(num_heads),
                emb=TransformerEmbeddings(Embedding(vocab_size, embedding_dim=hidden_dim)),
                transformer=StackedTransformerLayer(
                    num_layers,
                    layer=TransformerLayer(
                        self_attention=TransformerAttentionLayer(
                            target_dim=hidden_dim,
                            source_dim=hidden_dim,
                            num_heads=num_heads,
                            structure="prenorm",
                            norm="rmsnorm",
                            qkv_linear_cls=FusedQKVLinear,
                            linear_biases=False,
                        ),
                        feed_forward=TransformerFeedForwardLayer(
                            input_dim=hidden_dim,
                            hidden_dim=round(hidden_dim * (21.0 / 8.0)),
                            activation=(
                                _torch_activation_fn("nn.silu"),
                                _torch_activation_fn("linear"),
                            ),
                            structure="prenorm",
                            norm="rmsnorm",
                            linear_biases=False,
                        ),
                    ),
                ),
                output_norm="rmsnorm",
            )
        )
        return model


def __init__(
        self,
        *,
        input_size: tuple[int, int],
        num_masking_patches: int,
        num_attempts: int = 10,
        min_mask_patches: int = 16,
        min_aspect: float = 0.3,
        max_mask_patches: Optional[int] = None,
        max_aspect: Optional[float] = None,
    ):
        """Initializes MaskingGenerator.

        Args:
            input_size: an int tuple that represents (height, width) of the patchified target.
            num_masking_patches: the number of patches to be masked.
            num_attempts: the max number of attempts for one mask generation trial.
            min_mask_patches: the min number of patches for one masking area.
            max_mask_patches: the max number of patches for one masking area. If None, sets to
                num_masking_patches.
            min_aspect: the min aspect ratio (height/width) for one masking area.
            max_aspect: the max aspect ratio for one masking area. If None, sets to 1 / min_aspect.

        Raises:
            ValueError: if min_aspect or max_aspect are below 0 or max_aspect is smaller than
                min_aspect.
        """
        self.height, self.width = input_size
        # Total number of patches in the pachified input.
        self.num_patches = self.height * self.width
        self.num_masking_patches = num_masking_patches
        self.num_attempts = num_attempts
        self.min_mask_patches = min_mask_patches
        self.max_mask_patches = (
            num_masking_patches if max_mask_patches is None else max_mask_patches
        )
        max_aspect = max_aspect or 1 / min_aspect
        if min_aspect <= 0 or max_aspect <= 0:
            raise ValueError("Both min and max aspect ratios need to be positive.")
        if min_aspect > max_aspect:
            raise ValueError("min_aspect needs to be no greater than max_aspect.")
        self.log_aspect_ratio = (math.log(min_aspect), math.log(max_aspect))

def __init__(
        self,
        *,
        input_size: tuple[int, int],
        num_masking_patches: int,
        num_attempts: int = 10,
        min_mask_patches: int = 16,
        min_aspect: float = 0.3,
        max_mask_patches: Optional[int] = None,
        max_aspect: Optional[float] = None,
    ):

        self.height, self.width = input_size
        # Total number of patches in the pachified input.
        self.num_patches = self.height * self.width
        self.num_masking_patches = num_masking_patches
        self.num_attempts = num_attempts
        self.min_mask_patches = min_mask_patches
        self.max_mask_patches = (
            num_masking_patches if max_mask_patches is None else max_mask_patches
        )
        max_aspect = max_aspect or 1 / min_aspect
        if min_aspect <= 0 or max_aspect <= 0:
            raise ValueError("Both min and max aspect ratios need to be positive.")
        if min_aspect > max_aspect:
            raise ValueError("min_aspect needs to be no greater than max_aspect.")
        self.log_aspect_ratio = (math.log(min_aspect), math.log(max_aspect))


@property
    def endpoints_dims(self) -> dict[str, int]:
        """A dict of {endpoint: dim} specifies dimension of intermediate representations."""
        return self._endpoints_dims

@property
    def endpoints_dims(self) -> dict[str, int]:

        return self._endpoints_dims


def spatial_encoding(td: TensorDict):
    """We use a spatial encoing as proposed in GraphFormer (https://arxiv.org/abs/2106.05234)
    The spatial encoding in GraphFormer determines the distance of the shortest path between and
    nodes i and j and uses a special value for node pairs that cannot be connected at all.
    For any two operations i<j of the same job, we determine the number of operations to be completet
    when starting at i before j can be started (e.g. i=3 and j=5 -> e=2) and for i>j the negative number of
    operations that starting from j, have been completet before arriving at i (e.g. i=5 j=3 -> e=-2).
    For i=j we set e=0 as well as for operations of different jobs.

    :param torch.Tensor[bs, n_ops] ops_job_map: tensor specifying the index of its corresponding job
    :return torch.Tensor[bs, n_ops, n_ops]: length of shortest path between any two operations
    """
    bs, _, n_total_ops = td["job_ops_adj"].shape
    max_ops_per_job = int(td["job_ops_adj"].sum(-1).max())
    ops_job_map = td["ops_job_map"]
    pad_mask = td["pad_mask"]

    same_job = (ops_job_map[:, None] == ops_job_map[..., None]).to(torch.int32)
    # mask padded
    same_job[pad_mask.unsqueeze(2).expand_as(same_job)] = 0
    same_job[pad_mask.unsqueeze(1).expand_as(same_job)] = 0
    # take upper triangular of same_job and set diagonal to zero for counting purposes
    upper_tri = torch.triu(same_job) - torch.diag(
        torch.ones(n_total_ops, device=td.device)
    )[None].expand_as(same_job)
    # cumsum and masking of operations that do not belong to the same job
    num_jumps = upper_tri.cumsum(2) * upper_tri
    # mirror the matrix
    num_jumps = num_jumps + num_jumps.transpose(1, 2)
    # NOTE: shifted this logic into the spatial encoding module
    # num_jumps = num_jumps + (-num_jumps.transpose(1,2))
    assert not torch.any(num_jumps >= max_ops_per_job)
    # special value for ops of different jobs and self-loops
    num_jumps = torch.where(num_jumps == 0, -1, num_jumps)
    self_mask = torch.eye(n_total_ops).repeat(bs, 1, 1).bool()
    num_jumps[self_mask] = 0
    return num_jumps

def spatial_encoding(td: TensorDict):

    bs, _, n_total_ops = td["job_ops_adj"].shape
    max_ops_per_job = int(td["job_ops_adj"].sum(-1).max())
    ops_job_map = td["ops_job_map"]
    pad_mask = td["pad_mask"]

    same_job = (ops_job_map[:, None] == ops_job_map[..., None]).to(torch.int32)
    # mask padded
    same_job[pad_mask.unsqueeze(2).expand_as(same_job)] = 0
    same_job[pad_mask.unsqueeze(1).expand_as(same_job)] = 0
    # take upper triangular of same_job and set diagonal to zero for counting purposes
    upper_tri = torch.triu(same_job) - torch.diag(
        torch.ones(n_total_ops, device=td.device)
    )[None].expand_as(same_job)
    # cumsum and masking of operations that do not belong to the same job
    num_jumps = upper_tri.cumsum(2) * upper_tri
    # mirror the matrix
    num_jumps = num_jumps + num_jumps.transpose(1, 2)
    # NOTE: shifted this logic into the spatial encoding module
    # num_jumps = num_jumps + (-num_jumps.transpose(1,2))
    assert not torch.any(num_jumps >= max_ops_per_job)
    # special value for ops of different jobs and self-loops
    num_jumps = torch.where(num_jumps == 0, -1, num_jumps)
    self_mask = torch.eye(n_total_ops).repeat(bs, 1, 1).bool()
    num_jumps[self_mask] = 0
    return num_jumps


def _create_examples(self, lines, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, line) in enumerate(lines):
            guid = "%s-%s" % (set_type, i)
            text_a = line[3]
            label = line[1]
            examples.append(
                InputExample(guid=guid,
                             text_a=text_a,
                             text_b=None,
                             label=label))
        return examples

def _create_examples(self, lines, set_type):

        examples = []
        for (i, line) in enumerate(lines):
            guid = "%s-%s" % (set_type, i)
            text_a = line[3]
            label = line[1]
            examples.append(
                InputExample(guid=guid,
                             text_a=text_a,
                             text_b=None,
                             label=label))
        return examples


async def _get_database_proxy(self, **kwargs) -> DatabaseProxy:
        """Gets the database proxy."""
        try:
            if await self._does_database_exist():
                return self.cosmos_client.get_database_client(self.database_name)

            if self.create_database:
                return await self.cosmos_client.create_database(self.database_name, **kwargs)
            raise VectorStoreOperationException(f"Database '{self.database_name}' does not exist.")
        except Exception as e:
            raise VectorStoreOperationException(f"Failed to get database proxy for '{id}'.") from e

async def _get_database_proxy(self, **kwargs) -> DatabaseProxy:

        try:
            if await self._does_database_exist():
                return self.cosmos_client.get_database_client(self.database_name)

            if self.create_database:
                return await self.cosmos_client.create_database(self.database_name, **kwargs)
            raise VectorStoreOperationException(f"Database '{self.database_name}' does not exist.")
        except Exception as e:
            raise VectorStoreOperationException(f"Failed to get database proxy for '{id}'.") from e


def _get_underlying_type(annotation: Any) -> Any:
    """Get the underlying type of the annotation."""
    if isinstance(annotation, types.UnionType):
        return _get_non_none_type(annotation.__args__)

    if hasattr(annotation, "__origin__"):
        if annotation.__origin__ is Union:
            return _get_non_none_type(get_args(annotation))

        if isinstance(annotation.__origin__, types.UnionType):
            return _get_non_none_type(annotation.__origin__.__args__)

        return annotation.__origin__

    return annotation

def _get_underlying_type(annotation: Any) -> Any:

    if isinstance(annotation, types.UnionType):
        return _get_non_none_type(annotation.__args__)

    if hasattr(annotation, "__origin__"):
        if annotation.__origin__ is Union:
            return _get_non_none_type(get_args(annotation))

        if isinstance(annotation.__origin__, types.UnionType):
            return _get_non_none_type(annotation.__origin__.__args__)

        return annotation.__origin__

    return annotation


async def get_collections(self) -> list[str]:
        """Nullifies behavior of SemanticTextMemoryBase get_collections."""
        return []

async def get_collections(self) -> list[str]:

        return []


@pytest.fixture
def azure_cognitive_search_memory_store(azure_ai_search_unit_test_env):
    """Fixture to instantiate AzureCognitiveSearchMemoryStore with basic configuration."""
    return AzureCognitiveSearchMemoryStore(
        1536, "https://test.search.windows.net", azure_credentials=AzureKeyCredential("test_key")
    )

@pytest.fixture
def azure_cognitive_search_memory_store(azure_ai_search_unit_test_env):

    return AzureCognitiveSearchMemoryStore(
        1536, "https://test.search.windows.net", azure_credentials=AzureKeyCredential("test_key")
    )


def forward(self, *xs):
        """Forward pass.

        Returns:
            tensor: output
        """
        output = xs[0]

        if len(xs) == 2:
            res = self.resConfUnit1(xs[1])
            output = self.skip_add.add(output, res)
            # output += res

        output = self.resConfUnit2(output)

        output = nn.functional.interpolate(
            output, scale_factor=2, mode="bilinear", align_corners=self.align_corners
        )

        output = self.out_conv(output)

        return output

def forward(self, *xs):

        output = xs[0]

        if len(xs) == 2:
            res = self.resConfUnit1(xs[1])
            output = self.skip_add.add(output, res)
            # output += res

        output = self.resConfUnit2(output)

        output = nn.functional.interpolate(
            output, scale_factor=2, mode="bilinear", align_corners=self.align_corners
        )

        output = self.out_conv(output)

        return output


def posedict_to_pose(posedict: Dict[str, float]) -> List[float]:
    """Convert a posedict (from an emotion JSON) into a list of morph values (in the order the models expect them)."""
    # sanity check
    unrecognized_keys = set(posedict.keys()) - set(posedict_keys)
    if unrecognized_keys:
        logger.warning(f"posedict_to_pose: ignoring unrecognized keys in posedict: {unrecognized_keys}")
    # Missing keys are fine - keys for zero values can simply be omitted.

    pose = [0.0 for i in range(len(posedict_keys))]
    for idx, key in enumerate(posedict_keys):
        pose[idx] = posedict.get(key, 0.0)
    return pose

def posedict_to_pose(posedict: Dict[str, float]) -> List[float]:

    # sanity check
    unrecognized_keys = set(posedict.keys()) - set(posedict_keys)
    if unrecognized_keys:
        logger.warning(f"posedict_to_pose: ignoring unrecognized keys in posedict: {unrecognized_keys}")
    # Missing keys are fine - keys for zero values can simply be omitted.

    pose = [0.0 for i in range(len(posedict_keys))]
    for idx, key in enumerate(posedict_keys):
        pose[idx] = posedict.get(key, 0.0)
    return pose


def to_tensor(self, dtype, device):
        """See :func:`BaseInstanceMasks.to_tensor`."""
        if len(self.masks) == 0:
            return torch.empty((0, self.height, self.width),
                               dtype=dtype,
                               device=device)
        ndarray_masks = self.to_ndarray()
        return torch.tensor(ndarray_masks, dtype=dtype, device=device)

def to_tensor(self, dtype, device):

        if len(self.masks) == 0:
            return torch.empty((0, self.height, self.width),
                               dtype=dtype,
                               device=device)
        ndarray_masks = self.to_ndarray()
        return torch.tensor(ndarray_masks, dtype=dtype, device=device)


def __call__(self, results):
        """Call function to load proposals from file.

        Args:
            results (dict): Result dict from :obj:`mmdet.CustomDataset`.

        Returns:
            dict: The dict contains loaded proposal annotations.
        """

        proposals = results['proposals']
        if proposals.shape[1] not in (4, 5):
            raise AssertionError(
                'proposals should have shapes (n, 4) or (n, 5), '
                f'but found {proposals.shape}')
        proposals = proposals[:, :4]

        if self.num_max_proposals is not None:
            proposals = proposals[:self.num_max_proposals]

        if len(proposals) == 0:
            proposals = np.array([[0, 0, 0, 0]], dtype=np.float32)
        results['proposals'] = proposals
        results['bbox_fields'].append('proposals')
        return results

def __call__(self, results):

        proposals = results['proposals']
        if proposals.shape[1] not in (4, 5):
            raise AssertionError(
                'proposals should have shapes (n, 4) or (n, 5), '
                f'but found {proposals.shape}')
        proposals = proposals[:, :4]

        if self.num_max_proposals is not None:
            proposals = proposals[:self.num_max_proposals]

        if len(proposals) == 0:
            proposals = np.array([[0, 0, 0, 0]], dtype=np.float32)
        results['proposals'] = proposals
        results['bbox_fields'].append('proposals')
        return results


def forward(self, x):
        """Forward function."""
        if self.num_branches == 1:
            return [self.branches[0](x[0])]

        for i in range(self.num_branches):
            x[i] = self.branches[i](x[i])

        x_fuse = []
        for i in range(len(self.fuse_layers)):
            y = 0
            for j in range(self.num_branches):
                if i == j:
                    y += x[j]
                else:
                    y += self.fuse_layers[i][j](x[j])
            x_fuse.append(self.relu(y))
        return x_fuse

def forward(self, x):

        if self.num_branches == 1:
            return [self.branches[0](x[0])]

        for i in range(self.num_branches):
            x[i] = self.branches[i](x[i])

        x_fuse = []
        for i in range(len(self.fuse_layers)):
            y = 0
            for j in range(self.num_branches):
                if i == j:
                    y += x[j]
                else:
                    y += self.fuse_layers[i][j](x[j])
            x_fuse.append(self.relu(y))
        return x_fuse


@mmcv.jit(derivate=True, coderize=True)
def varifocal_loss(pred,
                   target,
                   weight=None,
                   alpha=0.75,
                   gamma=2.0,
                   iou_weighted=True,
                   reduction='mean',
                   avg_factor=None):
    """`Varifocal Loss <https://arxiv.org/abs/2008.13367>`_

    Args:
        pred (torch.Tensor): The prediction with shape (N, C), C is the
            number of classes
        target (torch.Tensor): The learning target of the iou-aware
            classification score with shape (N, C), C is the number of classes.
        weight (torch.Tensor, optional): The weight of loss for each
            prediction. Defaults to None.
        alpha (float, optional): A balance factor for the negative part of
            Varifocal Loss, which is different from the alpha of Focal Loss.
            Defaults to 0.75.
        gamma (float, optional): The gamma for calculating the modulating
            factor. Defaults to 2.0.
        iou_weighted (bool, optional): Whether to weight the loss of the
            positive example with the iou target. Defaults to True.
        reduction (str, optional): The method used to reduce the loss into
            a scalar. Defaults to 'mean'. Options are "none", "mean" and
            "sum".
        avg_factor (int, optional): Average factor that is used to average
            the loss. Defaults to None.
    """
    # pred and target should be of the same size
    assert pred.size() == target.size()
    pred_sigmoid = pred.sigmoid()
    target = target.type_as(pred)
    if iou_weighted:
        focal_weight = target * (target > 0.0).float() + \
            alpha * (pred_sigmoid - target).abs().pow(gamma) * \
            (target <= 0.0).float()
    else:
        focal_weight = (target > 0.0).float() + \
            alpha * (pred_sigmoid - target).abs().pow(gamma) * \
            (target <= 0.0).float()
    loss = F.binary_cross_entropy_with_logits(
        pred, target, reduction='none') * focal_weight
    loss = weight_reduce_loss(loss, weight, reduction, avg_factor)
    return loss

@mmcv.jit(derivate=True, coderize=True)
def varifocal_loss(pred,
                   target,
                   weight=None,
                   alpha=0.75,
                   gamma=2.0,
                   iou_weighted=True,
                   reduction='mean',
                   avg_factor=None):

    # pred and target should be of the same size
    assert pred.size() == target.size()
    pred_sigmoid = pred.sigmoid()
    target = target.type_as(pred)
    if iou_weighted:
        focal_weight = target * (target > 0.0).float() + \
            alpha * (pred_sigmoid - target).abs().pow(gamma) * \
            (target <= 0.0).float()
    else:
        focal_weight = (target > 0.0).float() + \
            alpha * (pred_sigmoid - target).abs().pow(gamma) * \
            (target <= 0.0).float()
    loss = F.binary_cross_entropy_with_logits(
        pred, target, reduction='none') * focal_weight
    loss = weight_reduce_loss(loss, weight, reduction, avg_factor)
    return loss


@staticmethod
    def get_people_manager():
        """
        Method that returns the current people manager.
        """
        return PeopleManager()

@staticmethod
    def get_people_manager():

        return PeopleManager()


def _convert_old_conf(console: Console, path: Path) -> str:
    """Reads old config file and converts it to the v2 toml."""
    cp = ConfigParser()
    cp.read_string(path.read_text())
    if not cp.has_section("default"):
        console.print(f"The config file {path!s} does not contain any configuration, nothing to migrate.")
        sys.exit(1)

    v1_config = dict(cp.items("default"))
    v2_config = v1_to_v2_config_dict(v1_config, env=False, get_config=False)
    v2_config_toml = tomli_w.dumps(v2_config)
    console.print(
        Markdown(f"Your v1 project config converted to the v2 format looks like this:\n```toml\n{v2_config_toml}\n```"),
    )
    return v2_config_toml

def _convert_old_conf(console: Console, path: Path) -> str:

    cp = ConfigParser()
    cp.read_string(path.read_text())
    if not cp.has_section("default"):
        console.print(f"The config file {path!s} does not contain any configuration, nothing to migrate.")
        sys.exit(1)

    v1_config = dict(cp.items("default"))
    v2_config = v1_to_v2_config_dict(v1_config, env=False, get_config=False)
    v2_config_toml = tomli_w.dumps(v2_config)
    console.print(
        Markdown(f"Your v1 project config converted to the v2 format looks like this:\n```toml\n{v2_config_toml}\n```"),
    )
    return v2_config_toml


def _resize_seg(self, results):
        """Resize semantic segmentation map with ``results['scale']``."""
        for key in results.get('seg_fields', []):
            if self.keep_ratio:
                gt_seg = mmcv.imrescale(
                    results[key],
                    results['scale'],
                    interpolation='nearest',
                    backend=self.backend)
            else:
                gt_seg = mmcv.imresize(
                    results[key],
                    results['scale'],
                    interpolation='nearest',
                    backend=self.backend)
            results[key] = gt_seg

def _resize_seg(self, results):

        for key in results.get('seg_fields', []):
            if self.keep_ratio:
                gt_seg = mmcv.imrescale(
                    results[key],
                    results['scale'],
                    interpolation='nearest',
                    backend=self.backend)
            else:
                gt_seg = mmcv.imresize(
                    results[key],
                    results['scale'],
                    interpolation='nearest',
                    backend=self.backend)
            results[key] = gt_seg


def simple_test(self, img, img_metas, rescale=False):
        """Test function without test time augmentation.

        Args:
            imgs (list[torch.Tensor]): List of multiple images
            img_metas (list[dict]): List of image information.
            rescale (bool, optional): Whether to rescale the results.
                Defaults to False.

        Returns:
            list[np.ndarray]: proposals
        """
        x = self.extract_feat(img)
        # get origin input shape to onnx dynamic input shape
        if torch.onnx.is_in_onnx_export():
            img_shape = torch._shape_as_tensor(img)[2:]
            img_metas[0]['img_shape_for_onnx'] = img_shape
        proposal_list = self.rpn_head.simple_test_rpn(x, img_metas)
        if rescale:
            for proposals, meta in zip(proposal_list, img_metas):
                proposals[:, :4] /= proposals.new_tensor(meta['scale_factor'])
        if torch.onnx.is_in_onnx_export():
            return proposal_list

        return [proposal.cpu().numpy() for proposal in proposal_list]

def simple_test(self, img, img_metas, rescale=False):

        x = self.extract_feat(img)
        # get origin input shape to onnx dynamic input shape
        if torch.onnx.is_in_onnx_export():
            img_shape = torch._shape_as_tensor(img)[2:]
            img_metas[0]['img_shape_for_onnx'] = img_shape
        proposal_list = self.rpn_head.simple_test_rpn(x, img_metas)
        if rescale:
            for proposals, meta in zip(proposal_list, img_metas):
                proposals[:, :4] /= proposals.new_tensor(meta['scale_factor'])
        if torch.onnx.is_in_onnx_export():
            return proposal_list

        return [proposal.cpu().numpy() for proposal in proposal_list]


@staticmethod
    def __get_site(data):
        """
        查询单个站点信息
        """
        tid = data.get("id")
        site_free = False
        site_2xfree = False
        site_hr = False
        if tid:
            ret = Sites().get_sites(siteid=tid)
            if ret.get("signurl"):
                site_attr = SiteConf().get_grap_conf(ret.get("signurl"))
                if site_attr.get("FREE"):
                    site_free = True
                if site_attr.get("2XFREE"):
                    site_2xfree = True
                if site_attr.get("HR"):
                    site_hr = True
        else:
            ret = []
        return {"code": 0, "site": ret, "site_free": site_free, "site_2xfree": site_2xfree, "site_hr": site_hr}

"""
        查询单个站点信息
        """

@staticmethod
    def __get_site(data):

        tid = data.get("id")
        site_free = False
        site_2xfree = False
        site_hr = False
        if tid:
            ret = Sites().get_sites(siteid=tid)
            if ret.get("signurl"):
                site_attr = SiteConf().get_grap_conf(ret.get("signurl"))
                if site_attr.get("FREE"):
                    site_free = True
                if site_attr.get("2XFREE"):
                    site_2xfree = True
                if site_attr.get("HR"):
                    site_hr = True
        else:
            ret = []
        return {"code": 0, "site": ret, "site_free": site_free, "site_2xfree": site_2xfree, "site_hr": site_hr}