

import unittest

from transformers import MODEL_FOR_ZERO_SHOT_OBJECT_DETECTION_MAPPING, is_vision_available, pipeline
from transformers.testing_utils import (
    is_pipeline_test,
    nested_simplify,
    require_tf,
    require_torch,
    require_vision,
    slow,
)

from .test_pipelines_common import ANY


if is_vision_available():
     from PIL import Image
else:



     class 						_A     :





       '''simple docstring'''



       @staticmethod
       def    snake_case_       (  *SCREAMING_SNAKE_CASE_   ,**SCREAMING_SNAKE_CASE_    ):

           '''simple docstring'''
           pass



@is_pipeline_test
@require_vision
@require_torch
class 						_A     (				unittest.TestCase				):





  '''simple docstring'''



  __lowerCamelCase			:      Dict					=   MODEL_FOR_ZERO_SHOT_OBJECT_DETECTION_MAPPING





  def    snake_case_       (  self   ,SCREAMING_SNAKE_CASE_   ,SCREAMING_SNAKE_CASE_   ,SCREAMING_SNAKE_CASE_    ):

      '''simple docstring'''
      snake_case							:		str        =		pipeline(
          """zero-shot-object-detection"""   ,model="""hf-internal-testing/tiny-random-owlvit-object-detection"""    )

      snake_case							:		List[Any]        =		[
          {
              """image""": """./tests/fixtures/tests_samples/COCO/000000039769.png""",
              """candidate_labels""": ["""cat""", """remote""", """couch"""],
          }
      ]
      return object_detector, examples





  def    snake_case_       (  self   ,SCREAMING_SNAKE_CASE_   ,SCREAMING_SNAKE_CASE_    ):

      '''simple docstring'''
      snake_case							:		List[str]        =		object_detector(examples[0]   ,threshold=0.0    )

      snake_case							:		Dict        =		len(SCREAMING_SNAKE_CASE_    )
      self.assertGreater(SCREAMING_SNAKE_CASE_   ,0    )
      self.assertEqual(
          SCREAMING_SNAKE_CASE_   ,[
              {
                  """score""": ANY(SCREAMING_SNAKE_CASE_    ),
                  """label""": ANY(SCREAMING_SNAKE_CASE_    ),
                  """box""": {"""xmin""": ANY(SCREAMING_SNAKE_CASE_    ), """ymin""": ANY(SCREAMING_SNAKE_CASE_    ), """xmax""": ANY(SCREAMING_SNAKE_CASE_    ), """ymax""": ANY(SCREAMING_SNAKE_CASE_    )},
              }
              for i in range(SCREAMING_SNAKE_CASE_    )
          ]   ,)





  @require_tf
  @unittest.skip("""Zero Shot Object Detection not implemented in TF"""    )
  def    snake_case_       (  self    ):

      '''simple docstring'''
      pass





  @require_torch
  def    snake_case_       (  self    ):

      '''simple docstring'''
      snake_case							:		str        =		pipeline(
          """zero-shot-object-detection"""   ,model="""hf-internal-testing/tiny-random-owlvit-object-detection"""    )

      snake_case							:		Union[str, Any]        =		object_detector(
          """./tests/fixtures/tests_samples/COCO/000000039769.png"""   ,candidate_labels=["""cat""", """remote""", """couch"""]   ,threshold=0.64   ,)

      self.assertEqual(
          nested_simplify(SCREAMING_SNAKE_CASE_   ,decimals=4    )   ,[
              {"""score""": 0.72_35, """label""": """cat""", """box""": {"""xmin""": 204, """ymin""": 167, """xmax""": 232, """ymax""": 190}},
              {"""score""": 0.72_18, """label""": """remote""", """box""": {"""xmin""": 204, """ymin""": 167, """xmax""": 232, """ymax""": 190}},
              {"""score""": 0.71_84, """label""": """couch""", """box""": {"""xmin""": 204, """ymin""": 167, """xmax""": 232, """ymax""": 190}},
              {"""score""": 0.67_48, """label""": """remote""", """box""": {"""xmin""": 571, """ymin""": 83, """xmax""": 598, """ymax""": 103}},
              {"""score""": 0.66_56, """label""": """cat""", """box""": {"""xmin""": 571, """ymin""": 83, """xmax""": 598, """ymax""": 103}},
              {"""score""": 0.66_14, """label""": """couch""", """box""": {"""xmin""": 571, """ymin""": 83, """xmax""": 598, """ymax""": 103}},
              {"""score""": 0.64_56, """label""": """remote""", """box""": {"""xmin""": 494, """ymin""": 105, """xmax""": 521, """ymax""": 127}},
              {"""score""": 0.6_42, """label""": """remote""", """box""": {"""xmin""": 67, """ymin""": 274, """xmax""": 93, """ymax""": 297}},
              {"""score""": 0.64_19, """label""": """cat""", """box""": {"""xmin""": 494, """ymin""": 105, """xmax""": 521, """ymax""": 127}},
          ]   ,)

      snake_case							:		Optional[int]        =		object_detector(
          [
              {
                  """image""": """./tests/fixtures/tests_samples/COCO/000000039769.png""",
                  """candidate_labels""": ["""cat""", """remote""", """couch"""],
              }
          ]   ,threshold=0.64   ,)

      self.assertEqual(
          nested_simplify(SCREAMING_SNAKE_CASE_   ,decimals=4    )   ,[
              [
                  {"""score""": 0.72_35, """label""": """cat""", """box""": {"""xmin""": 204, """ymin""": 167, """xmax""": 232, """ymax""": 190}},
                  {"""score""": 0.72_18, """label""": """remote""", """box""": {"""xmin""": 204, """ymin""": 167, """xmax""": 232, """ymax""": 190}},
                  {"""score""": 0.71_84, """label""": """couch""", """box""": {"""xmin""": 204, """ymin""": 167, """xmax""": 232, """ymax""": 190}},
                  {"""score""": 0.67_48, """label""": """remote""", """box""": {"""xmin""": 571, """ymin""": 83, """xmax""": 598, """ymax""": 103}},
                  {"""score""": 0.66_56, """label""": """cat""", """box""": {"""xmin""": 571, """ymin""": 83, """xmax""": 598, """ymax""": 103}},
                  {"""score""": 0.66_14, """label""": """couch""", """box""": {"""xmin""": 571, """ymin""": 83, """xmax""": 598, """ymax""": 103}},
                  {"""score""": 0.64_56, """label""": """remote""", """box""": {"""xmin""": 494, """ymin""": 105, """xmax""": 521, """ymax""": 127}},
                  {"""score""": 0.6_42, """label""": """remote""", """box""": {"""xmin""": 67, """ymin""": 274, """xmax""": 93, """ymax""": 297}},
                  {"""score""": 0.64_19, """label""": """cat""", """box""": {"""xmin""": 494, """ymin""": 105, """xmax""": 521, """ymax""": 127}},
              ]
          ]   ,)





  @require_torch
  @slow
  def    snake_case_       (  self    ):

      '''simple docstring'''
      snake_case							:		List[str]        =		pipeline("""zero-shot-object-detection"""    )

      snake_case							:		Dict        =		object_detector(
          """http://images.cocodataset.org/val2017/000000039769.jpg"""   ,candidate_labels=["""cat""", """remote""", """couch"""]   ,)
      self.assertEqual(
          nested_simplify(SCREAMING_SNAKE_CASE_   ,decimals=4    )   ,[
              {"""score""": 0.28_68, """label""": """cat""", """box""": {"""xmin""": 324, """ymin""": 20, """xmax""": 640, """ymax""": 373}},
              {"""score""": 0.2_77, """label""": """remote""", """box""": {"""xmin""": 40, """ymin""": 72, """xmax""": 177, """ymax""": 115}},
              {"""score""": 0.25_37, """label""": """cat""", """box""": {"""xmin""": 1, """ymin""": 55, """xmax""": 315, """ymax""": 472}},
              {"""score""": 0.14_74, """label""": """remote""", """box""": {"""xmin""": 335, """ymin""": 74, """xmax""": 371, """ymax""": 187}},
              {"""score""": 0.12_08, """label""": """couch""", """box""": {"""xmin""": 4, """ymin""": 0, """xmax""": 642, """ymax""": 476}},
          ]   ,)

      snake_case							:		int        =		object_detector(
          [
              {
                  """image""": """http://images.cocodataset.org/val2017/000000039769.jpg""",
                  """candidate_labels""": ["""cat""", """remote""", """couch"""],
              },
              {
                  """image""": """http://images.cocodataset.org/val2017/000000039769.jpg""",
                  """candidate_labels""": ["""cat""", """remote""", """couch"""],
              },
          ]   ,)
      self.assertEqual(
          nested_simplify(SCREAMING_SNAKE_CASE_   ,decimals=4    )   ,[
              [
                  {"""score""": 0.28_68, """label""": """cat""", """box""": {"""xmin""": 324, """ymin""": 20, """xmax""": 640, """ymax""": 373}},
                  {"""score""": 0.2_77, """label""": """remote""", """box""": {"""xmin""": 40, """ymin""": 72, """xmax""": 177, """ymax""": 115}},
                  {"""score""": 0.25_37, """label""": """cat""", """box""": {"""xmin""": 1, """ymin""": 55, """xmax""": 315, """ymax""": 472}},
                  {"""score""": 0.14_74, """label""": """remote""", """box""": {"""xmin""": 335, """ymin""": 74, """xmax""": 371, """ymax""": 187}},
                  {"""score""": 0.12_08, """label""": """couch""", """box""": {"""xmin""": 4, """ymin""": 0, """xmax""": 642, """ymax""": 476}},
              ],
              [
                  {"""score""": 0.28_68, """label""": """cat""", """box""": {"""xmin""": 324, """ymin""": 20, """xmax""": 640, """ymax""": 373}},
                  {"""score""": 0.2_77, """label""": """remote""", """box""": {"""xmin""": 40, """ymin""": 72, """xmax""": 177, """ymax""": 115}},
                  {"""score""": 0.25_37, """label""": """cat""", """box""": {"""xmin""": 1, """ymin""": 55, """xmax""": 315, """ymax""": 472}},
                  {"""score""": 0.14_74, """label""": """remote""", """box""": {"""xmin""": 335, """ymin""": 74, """xmax""": 371, """ymax""": 187}},
                  {"""score""": 0.12_08, """label""": """couch""", """box""": {"""xmin""": 4, """ymin""": 0, """xmax""": 642, """ymax""": 476}},
              ],
          ]   ,)





  @require_tf
  @unittest.skip("""Zero Shot Object Detection not implemented in TF"""    )
  def    snake_case_       (  self    ):

      '''simple docstring'''
      pass





  @require_torch
  @slow
  def    snake_case_       (  self    ):

      '''simple docstring'''
      snake_case							:		int        =		0.2
      snake_case							:		Dict        =		pipeline("""zero-shot-object-detection"""    )

      snake_case							:		int        =		object_detector(
          """http://images.cocodataset.org/val2017/000000039769.jpg"""   ,candidate_labels=["""cat""", """remote""", """couch"""]   ,threshold=SCREAMING_SNAKE_CASE_   ,)
      self.assertEqual(
          nested_simplify(SCREAMING_SNAKE_CASE_   ,decimals=4    )   ,[
              {"""score""": 0.28_68, """label""": """cat""", """box""": {"""xmin""": 324, """ymin""": 20, """xmax""": 640, """ymax""": 373}},
              {"""score""": 0.2_77, """label""": """remote""", """box""": {"""xmin""": 40, """ymin""": 72, """xmax""": 177, """ymax""": 115}},
              {"""score""": 0.25_37, """label""": """cat""", """box""": {"""xmin""": 1, """ymin""": 55, """xmax""": 315, """ymax""": 472}},
          ]   ,)





  @require_torch
  @slow
  def    snake_case_       (  self    ):

      '''simple docstring'''
      snake_case							:		Union[str, Any]        =		2
      snake_case							:		Dict        =		pipeline("""zero-shot-object-detection"""    )

      snake_case							:		str        =		object_detector(
          """http://images.cocodataset.org/val2017/000000039769.jpg"""   ,candidate_labels=["""cat""", """remote""", """couch"""]   ,top_k=SCREAMING_SNAKE_CASE_   ,)
      self.assertEqual(
          nested_simplify(SCREAMING_SNAKE_CASE_   ,decimals=4    )   ,[
              {"""score""": 0.28_68, """label""": """cat""", """box""": {"""xmin""": 324, """ymin""": 20, """xmax""": 640, """ymax""": 373}},
              {"""score""": 0.2_77, """label""": """remote""", """box""": {"""xmin""": 40, """ymin""": 72, """xmax""": 177, """ymax""": 115}},
          ]   ,)











"""simple docstring"""


import argparse
import json
import math
import os
import time
import traceback
import zipfile
from collections import Counter

import requests


def        UpperCAmelCase      (					a__     ,      a__=None ):





						'''simple docstring'''






						lowerCAmelCase   :str						=			None
						if token is not None:
												lowerCAmelCase   :List[Any]						=			{'Accept': 'application/vnd.github+json', 'Authorization': F"""Bearer {token}"""}

						lowerCAmelCase   :Dict						=			F"""https://api.github.com/repos/huggingface/transformers/actions/runs/{workflow_run_id}/jobs?per_page=100"""
						lowerCAmelCase   :Optional[Any]						=			requests.get(a__     ,      headers=a__ ).json()
						lowerCAmelCase   :Tuple						=			{}

						try:
												job_links.update({job['name']: job['html_url'] for job in result['jobs']} )
												lowerCAmelCase   :List[Any]						=			math.ceil((result['total_count'] - 1_00) / 1_00 )

												for i in range(a__ ):
																		lowerCAmelCase   :List[Any]						=			requests.get(url + F"""&page={i + 2}"""     ,      headers=a__ ).json()
																		job_links.update({job['name']: job['html_url'] for job in result['jobs']} )

												return job_links
						except Exception:
												print(F"""Unknown error, could not fetch links:\n{traceback.format_exc()}""" )

						return {}


def        UpperCAmelCase      (					a__     ,      a__=None ):





						'''simple docstring'''






						lowerCAmelCase   :Optional[Any]						=			None
						if token is not None:
												lowerCAmelCase   :Any						=			{'Accept': 'application/vnd.github+json', 'Authorization': F"""Bearer {token}"""}

						lowerCAmelCase   :Optional[int]						=			F"""https://api.github.com/repos/huggingface/transformers/actions/runs/{worflow_run_id}/artifacts?per_page=100"""
						lowerCAmelCase   :Any						=			requests.get(a__     ,      headers=a__ ).json()
						lowerCAmelCase   :str						=			{}

						try:
												artifacts.update({artifact['name']: artifact['archive_download_url'] for artifact in result['artifacts']} )
												lowerCAmelCase   :List[Any]						=			math.ceil((result['total_count'] - 1_00) / 1_00 )

												for i in range(a__ ):
																		lowerCAmelCase   :List[Any]						=			requests.get(url + F"""&page={i + 2}"""     ,      headers=a__ ).json()
																		artifacts.update({artifact['name']: artifact['archive_download_url'] for artifact in result['artifacts']} )

												return artifacts
						except Exception:
												print(F"""Unknown error, could not fetch links:\n{traceback.format_exc()}""" )

						return {}


def        UpperCAmelCase      (					a__     ,      a__     ,      a__     ,      a__ ):





						'''simple docstring'''






						lowerCAmelCase   :Optional[Any]						=			None
						if token is not None:
												lowerCAmelCase   :Optional[Any]						=			{'Accept': 'application/vnd.github+json', 'Authorization': F"""Bearer {token}"""}

						lowerCAmelCase   :Tuple						=			requests.get(a__     ,      headers=a__     ,      allow_redirects=a__ )
						lowerCAmelCase   :Optional[int]						=			result.headers['Location']
						lowerCAmelCase   :int						=			requests.get(a__     ,      allow_redirects=a__ )
						lowerCAmelCase   :Union[str, Any]						=			os.path.join(a__     ,      F"""{artifact_name}.zip""" )
						with open(a__     ,      'wb' ) as fp:
												fp.write(response.content )


def        UpperCAmelCase      (					a__     ,      a__=None ):





						'''simple docstring'''






						lowerCAmelCase   :Optional[Any]						=			[]
						lowerCAmelCase   :Dict						=			[]
						lowerCAmelCase   :Optional[Any]						=			None

						with zipfile.ZipFile(a__ ) as z:
												for filename in z.namelist():
																		if not os.path.isdir(a__ ):
																								# read the file
																								if filename in ["failures_line.txt", "summary_short.txt", "job_name.txt"]:
																														with z.open(a__ ) as f:
																																				for line in f:
																																										lowerCAmelCase   :int						=			line.decode('UTF-8' ).strip()
																																										if filename == "failures_line.txt":
																																																try:
																																																						# `error_line` is the place where `error` occurs
																																																						lowerCAmelCase   :int						=			line[: line.index(': ' )]
																																																						lowerCAmelCase   :int						=			line[line.index(': ' ) + len(': ' ) :]
																																																						errors.append([error_line, error] )
																																																except Exception:
																																																						# skip un-related lines
																																																						pass
																																										elif filename == "summary_short.txt" and line.startswith('FAILED ' ):
																																																# `test` is the test method that failed
																																																lowerCAmelCase   :int						=			line[len('FAILED ' ) :]
																																																failed_tests.append(a__ )
																																										elif filename == "job_name.txt":
																																																lowerCAmelCase   :List[str]						=			line

						if len(a__ ) != len(a__ ):
												raise ValueError(
												    F"""`errors` and `failed_tests` should have the same number of elements. Got {len(a__ )} for `errors` """
												    F"""and {len(a__ )} for `failed_tests` instead. The test reports in {artifact_zip_path} have some"""
												    ' problem.' )

						lowerCAmelCase   :Optional[int]						=			None
						if job_name and job_links:
												lowerCAmelCase   :Dict						=			job_links.get(a__     ,      a__ )

						# A list with elements of the form (line of error, error, failed test)
						lowerCAmelCase   :Union[str, Any]						=			[x + [y] + [job_link] for x, y in zip(a__     ,      a__ )]

						return result


def        UpperCAmelCase      (					a__     ,      a__=None ):





						'''simple docstring'''






						lowerCAmelCase   :Any						=			[]

						lowerCAmelCase   :Optional[int]						=			[os.path.join(a__     ,      a__ ) for p in os.listdir(a__ ) if p.endswith('.zip' )]
						for p in paths:
												errors.extend(get_errors_from_single_artifact(a__     ,      job_links=a__ ) )

						return errors


def        UpperCAmelCase      (					a__     ,      a__=None ):





						'''simple docstring'''






						lowerCAmelCase   :int						=			Counter()
						counter.update([x[1] for x in logs] )
						lowerCAmelCase   :Tuple						=			counter.most_common()
						lowerCAmelCase   :Dict						=			{}
						for error, count in counts:
												if error_filter is None or error not in error_filter:
																		lowerCAmelCase   :Optional[int]						=			{'count': count, 'failed_tests': [(x[2], x[0]) for x in logs if x[1] == error]}

						lowerCAmelCase   :Optional[Any]						=			dict(sorted(r.items()     ,      key=lambda a__ : item[1]["count"]     ,      reverse=a__ ) )
						return r


def        UpperCAmelCase      (					a__ ):





						'''simple docstring'''






						lowerCAmelCase   :Tuple						=			test.split('::' )[0]
						if test.startswith('tests/models/' ):
												lowerCAmelCase   :Union[str, Any]						=			test.split('/' )[2]
						else:
												lowerCAmelCase   :Optional[int]						=			None

						return test


def        UpperCAmelCase      (					a__     ,      a__=None ):





						'''simple docstring'''






						lowerCAmelCase   :str						=			[(x[0], x[1], get_model(x[2] )) for x in logs]
						lowerCAmelCase   :Any						=			[x for x in logs if x[2] is not None]
						lowerCAmelCase   :Tuple						=			{x[2] for x in logs}

						lowerCAmelCase   :Optional[Any]						=			{}
						for test in tests:
												lowerCAmelCase   :Union[str, Any]						=			Counter()
												# count by errors in `test`
												counter.update([x[1] for x in logs if x[2] == test] )
												lowerCAmelCase   :List[str]						=			counter.most_common()
												lowerCAmelCase   :str						=			{error: count for error, count in counts if (error_filter is None or error not in error_filter)}
												lowerCAmelCase   :Optional[Any]						=			sum(error_counts.values() )
												if n_errors > 0:
																		lowerCAmelCase   :Dict						=			{'count': n_errors, 'errors': error_counts}

						lowerCAmelCase   :Dict						=			dict(sorted(r.items()     ,      key=lambda a__ : item[1]["count"]     ,      reverse=a__ ) )
						return r


def        UpperCAmelCase      (					a__ ):





						'''simple docstring'''






						lowerCAmelCase   :Any						=			'| no. | error | status |'
						lowerCAmelCase   :Optional[int]						=			'|-:|:-|:-|'
						lowerCAmelCase   :Tuple						=			[header, sep]
						for error in reduced_by_error:
												lowerCAmelCase   :Optional[Any]						=			reduced_by_error[error]['count']
												lowerCAmelCase   :List[str]						=			F"""| {count} | {error[:1_00]} |  |"""
												lines.append(a__ )

						return "\n".join(a__ )


def        UpperCAmelCase      (					a__ ):





						'''simple docstring'''






						lowerCAmelCase   :Any						=			'| model | no. of errors | major error | count |'
						lowerCAmelCase   :int						=			'|-:|-:|-:|-:|'
						lowerCAmelCase   :int						=			[header, sep]
						for model in reduced_by_model:
												lowerCAmelCase   :Dict						=			reduced_by_model[model]['count']
												lowerCAmelCase	, lowerCAmelCase   :Any						=			list(reduced_by_model[model]['errors'].items() )[0]
												lowerCAmelCase   :Any						=			F"""| {model} | {count} | {error[:60]} | {_count} |"""
												lines.append(a__ )

						return "\n".join(a__ )


if __name__ == "__main__":
		__SCREAMING_SNAKE_CASE   =   argparse.ArgumentParser()
		# Required parameters
		parser.add_argument('--workflow_run_id', type=str, required=True, help='A GitHub Actions workflow run id.')
		parser.add_argument(
		    '--output_dir',
		    type=str,
		    required=True,
		    help='Where to store the downloaded artifacts and other result files.',
		)
		parser.add_argument('--token', default=None, type=str, help='A token that has actions:read permission.')
		__SCREAMING_SNAKE_CASE   =   parser.parse_args()

		os.makedirs(args.output_dir, exist_ok=True)

		__SCREAMING_SNAKE_CASE   =   get_job_links(args.workflow_run_id, token=args.token)
		__SCREAMING_SNAKE_CASE   =   {}
		# To deal with `workflow_call` event, where a job name is the combination of the job names in the caller and callee.
		# For example, `PyTorch 1.11 / Model tests (models/albert, single-gpu)`.
		if _job_links:
				for k, v in _job_links.items():
						# This is how GitHub actions combine job names.
						if " / " in k:
								__SCREAMING_SNAKE_CASE   =   k.find(' / ')
								__SCREAMING_SNAKE_CASE   =   k[index + len(' / ') :]
						__SCREAMING_SNAKE_CASE   =   v
		with open(os.path.join(args.output_dir, 'job_links.json'), 'w', encoding='UTF-8') as fp:
				json.dump(job_links, fp, ensure_ascii=False, indent=4)

		__SCREAMING_SNAKE_CASE   =   get_artifacts_links(args.workflow_run_id, token=args.token)
		with open(os.path.join(args.output_dir, 'artifacts.json'), 'w', encoding='UTF-8') as fp:
				json.dump(artifacts, fp, ensure_ascii=False, indent=4)

		for idx, (name, url) in enumerate(artifacts.items()):
				download_artifact(name, url, args.output_dir, args.token)
				# Be gentle to GitHub
				time.sleep(1)

		__SCREAMING_SNAKE_CASE   =   get_all_errors(args.output_dir, job_links=job_links)

		# `e[1]` is the error
		__SCREAMING_SNAKE_CASE   =   Counter()
		counter.update([e[1] for e in errors])

		# print the top 30 most common test errors
		__SCREAMING_SNAKE_CASE   =   counter.most_common(30)
		for item in most_common:
				print(item)

		with open(os.path.join(args.output_dir, 'errors.json'), 'w', encoding='UTF-8') as fp:
				json.dump(errors, fp, ensure_ascii=False, indent=4)

		__SCREAMING_SNAKE_CASE   =   reduce_by_error(errors)
		__SCREAMING_SNAKE_CASE   =   reduce_by_model(errors)

		__SCREAMING_SNAKE_CASE   =   make_github_table(reduced_by_error)
		__SCREAMING_SNAKE_CASE   =   make_github_table_per_model(reduced_by_model)

		with open(os.path.join(args.output_dir, 'reduced_by_error.txt'), 'w', encoding='UTF-8') as fp:
				fp.write(sa)
		with open(os.path.join(args.output_dir, 'reduced_by_model.txt'), 'w', encoding='UTF-8') as fp:
				fp.write(sa)