import cv2 as cv
from cv2 import waitKey
from numpy import int0, uint8

class Detect:
    def color_test(source):
        values = Detect.Settings.get_values()
        source = cv.GaussianBlur(source, (7, 7), 0)

        mask = Detect._create_mask(
            source,
            (
                values[Detect.Settings.H1],
                values[Detect.Settings.S1],
                values[Detect.Settings.V1],
            ),
            (
                values[Detect.Settings.H2],
                values[Detect.Settings.S2],
                values[Detect.Settings.V2]
            )
        )

        cv.imshow("threshold", mask)

    def _create_mask(source, hsv_min, hsv_max):
        hsv_min = Detect.Colors.cvstd(*hsv_min)
        hsv_max = Detect.Colors.cvstd(*hsv_max)

        hsv_image = cv.cvtColor(source, cv.COLOR_BGR2HSV)

        return cv.inRange(hsv_image, hsv_min, hsv_max)

    def demo(self, source, min_area=None, max_area=None):
        blur = cv.GaussianBlur(source, (7, 7), 0)

        mask_pink = Detect._create_mask(
            blur,
            Detect.Colors.PINK[0],
            Detect.Colors.PINK[1]
        )

        mask_blue = Detect._create_mask(
            blur,
            Detect.Colors.BLUE[0],
            Detect.Colors.BLUE[1]
        )

        mask_orange = Detect._create_mask(
            blur,
            Detect.Colors.ORANGE[0],
            Detect.Colors.ORANGE[1]
        )

        mask = mask_pink | mask_blue | mask_orange
        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

        if min_area == None and max_area == None:
            min_area = Detect.Settings.get_values()[Detect.Settings.MIN_AREA]
            max_area = Detect.Settings.get_values()[Detect.Settings.MAX_AREA]

        count = 0
        for contour in contours:
            rect = cv.minAreaRect(contour)
            box = cv.boxPoints(rect)
            box = int0(box)

            area = cv.contourArea(contour)
            if area >= min_area and area <= max_area:
                cv.drawContours(source, [box], -1, (255, 255, 255), 2)
                count += 1

        print(min_area, max_area, count)

        return str(count)

    def detect(
            self,
            source,
            thr_min,
            thr_max,
            blur,
            min_area,
            max_area
        ):

        image = source.copy()

        source = cv.cvtColor(source, cv.COLOR_BGR2GRAY)

        _, source = cv.threshold(source, thr_min, thr_max, cv.THRESH_BINARY)
        if blur:
            source = cv.medianBlur(source, blur)

        cv.imshow("image_thr", source)
        cv.waitKey()

        contours, _ = cv.findContours(source, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

        count = 0
        for contour in contours:
            rect = cv.minAreaRect(contour)
            box = cv.boxPoints(rect)
            box = int0(box)

            x1, y1 = box[0]
            x2, y2 = box[1]
            x3, y3 = box[2]

            a = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)
            a **= 1/2

            b = (x3 - x1)*(x3 - x1) + (y3 - y1)*(y3 - y1)
            b **= 1/2

            area = a*b
            coeff = b/a

            if (
                (area > min_area and area < max_area) and
                (coeff > 1.01 and coeff < 1.04)
            ):
                print(a*b, b/a, "", sep="\n")
                cv.drawContours(image, [box], -1, (255, 255, 0), 2)
                cv.imshow("image", image)
                cv.waitKey()
                count += 1

        print(count)
        cv.imshow("image", image)
        cv.destroyAllWindows()

    class Settings:
        WIN_NAME = "settings"

        H1 = "H1"
        S1 = "S1"
        V1 = "V1"

        H2 = "H2"
        S2 = "S2"
        V2 = "V2"

        MIN_AREA = "MIN_AREA"
        MAX_AREA = "MAX_AREA"

        AREA = 5000

        def __init__(self):
            cv.namedWindow(self.WIN_NAME, cv.WINDOW_NORMAL)

            cv.createTrackbar(self.H1, self.WIN_NAME, 0, 360, self.void)
            cv.createTrackbar(self.S1, self.WIN_NAME, 0, 100, self.void)
            cv.createTrackbar(self.V1, self.WIN_NAME, 0, 100, self.void)

            cv.createTrackbar(self.H2, self.WIN_NAME, 0, 360, self.void)
            cv.createTrackbar(self.S2, self.WIN_NAME, 0, 100, self.void)
            cv.createTrackbar(self.V2, self.WIN_NAME, 0, 100, self.void)

            cv.createTrackbar(self.MIN_AREA, self.WIN_NAME, 0, self.AREA, self.void)
            cv.createTrackbar(self.MAX_AREA, self.WIN_NAME, 0, self.AREA, self.void)

        def get_values():
            return {
                Detect.Settings.H1: cv.getTrackbarPos(Detect.Settings.H1, Detect.Settings.WIN_NAME),
                Detect.Settings.S1: cv.getTrackbarPos(Detect.Settings.S1, Detect.Settings.WIN_NAME),
                Detect.Settings.V1: cv.getTrackbarPos(Detect.Settings.V1, Detect.Settings.WIN_NAME),

                Detect.Settings.H2: cv.getTrackbarPos(Detect.Settings.H2, Detect.Settings.WIN_NAME),
                Detect.Settings.S2: cv.getTrackbarPos(Detect.Settings.S2, Detect.Settings.WIN_NAME),
                Detect.Settings.V2: cv.getTrackbarPos(Detect.Settings.V2, Detect.Settings.WIN_NAME),

                Detect.Settings.MIN_AREA: cv.getTrackbarPos(Detect.Settings.MIN_AREA, Detect.Settings.WIN_NAME),
                Detect.Settings.MAX_AREA: cv.getTrackbarPos(Detect.Settings.MAX_AREA, Detect.Settings.WIN_NAME)
            }

        def set_values(values):
            cv.setTrackbarPos(Detect.Settings.H1, Detect.Settings.WIN_NAME, values[0][0])
            cv.setTrackbarPos(Detect.Settings.S1, Detect.Settings.WIN_NAME, values[0][1])
            cv.setTrackbarPos(Detect.Settings.V1, Detect.Settings.WIN_NAME, values[0][2])

            cv.setTrackbarPos(Detect.Settings.H2, Detect.Settings.WIN_NAME, values[1][0])
            cv.setTrackbarPos(Detect.Settings.S2, Detect.Settings.WIN_NAME, values[1][1])
            cv.setTrackbarPos(Detect.Settings.V2, Detect.Settings.WIN_NAME, values[1][2])

        def void(*args, **kwargs): pass

    class Colors:
        PINK = (
            (257, 13, 53),
            (360, 100, 100)
        )

        ORANGE = (
            (0, 51, 39),
            (54, 100, 100)
        )

        BLUE = (
            (170, 64, 63),
            (214, 100, 100)
        )

        def cvstd(H, S, V):
            return uint8([
                    (H/360) * 180,
                    (S/100) * 255,
                    (V/100) * 255
                ])

        def increase_brightness(source, value=30):
            hsv = cv.cvtColor(source, cv.COLOR_BGR2HSV)
            h, s, v = cv.split(hsv)

            lim = 255 - value
            v[v > lim] = 255
            v[v <= lim] += value

            hsv = cv.merge((h, s, v))
            return cv.cvtColor(hsv, cv.COLOR_HSV2BGR)

class SettingsProduction:
    #THR
    THRESHOLD_MIN = 150
    THRESHOLD_MAX = 255

    #BLUR
    BLUR = 3

    #AREA
    MIN_AREA = 4220
    MAX_AREA = 4740

    #PERI
    PERI_COEFF = 0.01

if __name__ == "__main__":
    detect = Detect()
    detect.Settings()

    Detect.Settings.set_values(Detect.Colors.ORANGE)

    camera = cv.VideoCapture(1)
    while True:
        res, source = camera.read()
        # source = cv.resize(source,
        #     (int(len(source[0])*1.5),
        #     int(len(source)*1.5))
        # )

        color_test = 0
        if not color_test:
            print(detect.demo(source))
        else:
            Detect.color_test(source)

        cv.imshow("source", source)

        if waitKey(1) == 27:
            cv.destroyAllWindows()
            break


from base import baseResource
import json
import pycountry
import hashlib
from bson import Binary, Code, json_util, BSON, ObjectId
from bson.json_util import dumps

class elasticBasedResource(baseResource):
	def __init__(self):
		super(elasticBasedResource, self).__init__()

	def _queryMedia(self, coreid, mediaIDs):
		mediaURLs = []
		mediaQuery = {"query": {"term": {"coreid.keyword": coreid}}}
		mediaRes = self.es.search(index="idigbio_media2", body=mediaQuery)
		if mediaRes:
			for media in mediaRes['hits']['hits']:
				mediaURLs.append(media['_source']['ac:accessURI'])
		return mediaURLs

	def processSearchTerms(self, params, idigbioReplacements, pbdbReplacements):

		limit = self.limit()
		idbQuery = {
		   "size": limit,
		   "query":{
			   "bool":{
				   "must":[]
			   }
		   },
		   "sort": [
			   "_score",
			   "_doc"
		   ]
		}

		pbdbQuery = {
		   "size": limit,
		   "query":{
			   "bool":{
				   "must":[]
			   }
		   },
		   "sort": [
			   "_score",
			   "_doc"
		   ]
		}

		processed = {'idbQuery': idbQuery, 'pbdbQuery': pbdbQuery }
		if params['terms'] == None:
			processed['idbQuery']['query']['bool']['must'].append({'match_all': {}})
			processed['pbdbQuery']['query']['bool']['must'].append({'match_all': {}})
			return processed

		searchTerms = params['terms'].split('|')
		for search in searchTerms:
			pbdbAdded = False
			idbAdded = False
			try:
				field, term = search.split(':')
			except ValueError:
				# Without a field component we treat this as a query against all fields
				field = None
				term = search
				processed['idbQuery']['query']['bool']['must'].append({"query_string": {"query": '"' + term + '"'}})
				processed['pbdbQuery']['query']['bool']['must'].append({"query_string": {"query": '"' + term + '"'}})
				idbAdded = True
				pbdbAdded = True
			# Translate terms for iDigBio
			if field in idigbioReplacements:
				processed['idbQuery']['query']['bool']['must'].append({"term": {idigbioReplacements[field]: term}})
				idbAdded = True
			# Translate terms for PBDB
			if field in pbdbReplacements:
				if field == 'country':
					ccParts = term.split(' ')
					for i in range(len(ccParts)):
						ccParts[i] = ccParts[i][0].upper() + ccParts[i][1:]

					countryTerm = ' '.join(ccParts)

					try:
						country = pycountry.countries.get(name=countryTerm)
						countryCode = country.alpha_2
						term = countryCode
					except KeyError:
						errmsg = "The country provided in the terms query could not be found. Please check your query and provide a valid country name"
						return self.respondWithError(errmsg)

				processed['pbdbQuery']['query']['bool']['must'].append({"term": {pbdbReplacements[field]: term}})
				pbdbAdded = True

			# Add Translated Terms to ES Query
			if idbAdded is False:
				processed['idbQuery']['query']['bool']['must'].append({"term": {field: term}})
			if pbdbAdded is False:
				processed['pbdbQuery']['query']['bool']['must'].append({"term": {field: term}})

		# Default query if no params were given
		if len(processed['idbQuery']['query']['bool']['must']) == 0:
			processed['idbQuery']['query']['bool']['must'] = {'match_all': {}}
		if len(processed['pbdbQuery']['query']['bool']['must']) == 0:
			processed['pbdbQuery']['query']['bool']['must'] = {'match_all': {}}

		return processed
	# geoPoint v paleoGeoPoint
	def addGeoFilters(self, idbQuery, pbdbQuery, geoParam):
		paramParts = geoParam.split('|')
		coords = paramParts[0].split(';')
		matchRadius = 10
		if len(paramParts) > 1:
			try:
				matchRadius = int(paramParts[1])
			except ValueError:
				pass
		matchDistance = str(matchRadius) + 'km'

		matchField = None
		if len(paramParts) > 2:
			matchField = paramParts[2].lower()

		queries = [(idbQuery, 'idigbio:geoPoint'), (pbdbQuery, 'geoPoint')]
		if matchField == 'paleo' or matchField == 'paleogeopoint':
			idbQuery = None
			queries = [(pbdbQuery, 'paleoGeoPoint'), (idbQuery, None)]

		for query in queries:
			if query[0] is None:
				continue
			if len(coords) == 1:
				geoFilter = {'geo_distance': {'distance': matchDistance, query[1]: coords[0]}}
			elif len(coords) == 2:
				geoFilter = {'geo_bounding_box': {query[1]: {"top_left": coords[0], "bottom_right": coords[1]}}}
			elif len(coords) > 2:
				geoFilter = {'geo_polygon': {query[1]: {"points": coords}}}
			query[0]['query']['bool']['filter'] = geoFilter

		return pbdbQuery, idbQuery

	def getLocalityMatch(self, matchLevel):
		localityMatch = {'idigbio': 'dwc:county', 'pbdb': 'county'}
		if matchLevel:
			matchLevel = matchLevel.lower()
			localityMatch['pbdb'] = matchLevel
			localityMatch['idigbio'] = 'dwc:' + matchLevel
			if matchLevel == 'state':
				localityMatch['idigbio'] = localityMatch['idigbio'] + 'Province'
			elif matchLevel == 'country':
				localityMatch['pbdb'] = 'cc1'
		return localityMatch

	def getTaxonMatch(self, matchLevel, idigbioReplacements, pbdbReplacements):
		taxonMatch = {'idigbio': 'dwc:genus', 'pbdb': 'genus'}
		if matchLevel:
			matchLevel = matchLevel.lower()
			if matchLevel in idigbioReplacements:
				taxonMatch['idigbio'] = idigbioReplacements[matchLevel]
			else:
				taxonMatch['idigbio'] = 'dwc:' + matchLevel
			if matchLevel in pbdbReplacements:
				taxonMatch['pbdb'] = pbdbReplacements[matchLevel]
			else:
				taxonMatch['pbdb'] = matchLevel

		return taxonMatch

	def getChronoMatch(self, matchLevel):
		chronoMatch = {'idigbio': {'early': 'dwc:earliestPeriodOrLowestSystem', 'late': 'dwc:latestPeriodOrHighestSystem'}}
		chronoMatchLevel = None
		if matchLevel:
			matchLevel = matchLevel.lower()
			chronoMatchLevel = matchLevel
			if matchLevel == 'age':
				chronoMatch = {'idigbio': {'early': 'dwc:earliestAgeOrLowestStage', 'late': 'dwc:latestAgeOrHighestStage'}}
			elif matchLevel == 'epoch':
				chronoMatch = {'idigbio': {'early': 'dwc:earliestEpochOrLowestSeries', 'late': 'dwc:latestEpochOrHighestSeries'}}
			elif matchLevel == 'era':
				chronoMatch = {'idigbio': {'early': 'dwc:earliestEraOrLowestErathem', 'late': 'dwc:latestEraOrHighestErathem'}}
		else:
			chronoMatchLevel = 'period'
		return chronoMatch, chronoMatchLevel

	def parseMatches(self, params, idbRes, pbdbRes, taxonMatch, localityMatch, chronoMatch, chronoMatchLevel, returnMedia=False, mediaOnly=False, pbdbType='occs'):

		matches = {'results': {}}
		if mediaOnly:
			mediaMatches = {'mediaURLs': []}
		for res in [pbdbRes, idbRes]:
			if res['hits']['total'] == 0:
				continue

			if res['hits']['hits'][0]['_type'] == 'idigbio':
				matches['idigbio_search_after'] = json.dumps(res['hits']['hits'][-1]['sort'])
				if mediaOnly:
					mediaMatches['idigbio_search_after'] = json.dumps(res['hits']['hits'][-1]['sort'])
			else:
				matches['pbdb_search_after'] = json.dumps(res['hits']['hits'][-1]['sort'])
				if mediaOnly:
					mediaMatches['pbdb_search_after'] = json.dumps(res['hits']['hits'][-1]['sort'])

			for hit in res['hits']['hits']:

				recHash = hashlib.sha1()
				data = {'sourceRecords': [], 'links': [], 'matchFields': {}}

				idbMatchList = []
				pbdbMatchList = []
				noMatch = False

				if hit['_type'] == 'idigbio':

					# Store the primary ID
					linkID = hit['_source']['idigbio:uuid']
					linkField= 'idigbio:uuid'

					# iDigBio Locality Matches
					if hit['_source'][localityMatch['idigbio']] is not None:
						idbMatchList.append({"match": {localityMatch['idigbio']: hit['_source'][localityMatch['idigbio']]}})
						data['matchFields'][localityMatch['idigbio']] = hit['_source'][localityMatch['idigbio']]
						recHash.update(data['matchFields'][localityMatch['idigbio']].encode('utf-8'))

						if params['localityMatchLevel']:
							ccParts = hit['_source'][localityMatch['idigbio']].split(' ')
							for i in range(len(ccParts)):
								ccParts[i] = ccParts[i][0].upper() + ccParts[i][1:]

							countryTerm = ' '.join(ccParts)

							try:
								country = pycountry.countries.get(name=countryTerm)
								pbdbMatchList.append({"match": {localityMatch['pbdb']: country.alpha_2}})
							except KeyError:
								noMatch = True
						else:
							pbdbMatchList.append({"match": {localityMatch['pbdb']: hit['_source'][localityMatch['idigbio']]}})

					else:
						noMatch = True

					# iDigBio Taxon Matches
					if hit['_source'][taxonMatch['idigbio']] is not None:
						pbdbMatchList.append({"match": {taxonMatch['pbdb']: hit['_source'][taxonMatch['idigbio']]}})
						idbMatchList.append({"match": {taxonMatch['idigbio']: hit['_source'][taxonMatch['idigbio']]}})
						data['matchFields'][taxonMatch['idigbio']] = hit['_source'][taxonMatch['idigbio']]
						recHash.update(data['matchFields'][taxonMatch['idigbio']])
					else:
						noMatch = True

					# iDigBio Chronostrat Matches
					chrono_early = chrono_late = None
					ma_start_score = ma_end_score = 0
					ma_start = 1000
					ma_end = 0

					if hit['_source'][chronoMatch['idigbio']['early']] and hit['_source'][chronoMatch['idigbio']['late']]:

						chrono_early = hit['_source'][chronoMatch['idigbio']['early']]
						chrono_late = hit['_source'][chronoMatch['idigbio']['late']]

						idbMatchList.append({"match": {chronoMatch['idigbio']['early']: hit['_source'][chronoMatch['idigbio']['early']]}})
						idbMatchList.append({"match": {chronoMatch['idigbio']['late']: hit['_source'][chronoMatch['idigbio']['late']]}})
					elif hit['_source'][chronoMatch['idigbio']['early']]:

						chrono_early = hit['_source'][chronoMatch['idigbio']['early']]
						chrono_late = hit['_source'][chronoMatch['idigbio']['early']]

						idbMatchList.append({"match": {chronoMatch['idigbio']['early']: hit['_source'][chronoMatch['idigbio']['early']]}})
						idbMatchList.append({"match": {chronoMatch['idigbio']['late']: hit['_source'][chronoMatch['idigbio']['early']]}})
					elif hit['_source'][chronoMatch['idigbio']['late']]:

						chrono_early = hit['_source'][chronoMatch['idigbio']['late']]
						chrono_late = hit['_source'][chronoMatch['idigbio']['late']]

						idbMatchList.append({"match": {chronoMatch['idigbio']['early']: hit['_source'][chronoMatch['idigbio']['late']]}})
						idbMatchList.append({"match": {chronoMatch['idigbio']['late']: hit['_source'][chronoMatch['idigbio']['late']]}})
					else:
						noMatch = True

					# Do chronoLookup query if chrono_eary and chrono_late are set
					if chrono_early and chrono_late:

						# Late Query
						ma_start_res = self.es.search(index="chronolookup", body={"query": {"match": {"name": chrono_late}}})
						for ma_start_hit in ma_start_res['hits']['hits']:
							if ma_start_hit['_source']['level'] == chronoMatchLevel:
								if hit['_score'] > ma_start_score:
									ma_start = ma_start_hit['_source']['start_ma']
									ma_start_score = ma_start_hit['_score']

						# Early Query
						ma_end_res = self.es.search(index="chronolookup", body={"query": {"match": {"name": chrono_early}}})
						for ma_end_hit in ma_end_res['hits']['hits']:
							if ma_end_hit['_source']['level'] == chronoMatchLevel:
								if hit['_score'] > ma_end_score:
									ma_end = ma_start_hit['_source']['end_ma']
									ma_end_score = ma_start_hit['_score']

						data['matchFields']['chronostratigraphy'] = {"max_ma": ma_start, "min_ma": ma_end}

						pbdbMatchList.append({"range": {"min_ma": {"lte": ma_start}}})
						pbdbMatchList.append({"range": {"max_ma": {"gte": ma_end}}})

					recHash.update( str(ma_start) + str(ma_end) )
					linkQuery = {
						"size": 10,
						"query":{
							"bool":{
								"must": pbdbMatchList
							}
						}
					}
					queryIndex = 'pbdb'

				elif hit['_type'] == 'pbdb':

					# PBDB Locality Matches
					if hit['_source'][localityMatch['pbdb']] is not None:

						if params['localityMatchLevel'] == 'country':
							try:
								country = pycountry.countries.get(alpha_2=hit['_source'][localityMatch['pbdb']])
								idbMatchList.append({"match": {localityMatch['idigbio']: country.name}})
							except KeyError:
								noMatch = True
						else:
							idbMatchList.append({"match": {localityMatch['idigbio']: hit['_source'][localityMatch['pbdb']]}})

						pbdbMatchList.append({"match": {localityMatch['pbdb']: hit['_source'][localityMatch['pbdb']]}})
						data['matchFields'][localityMatch['pbdb']] = hit['_source'][localityMatch['pbdb']]
						recHash.update(data['matchFields'][localityMatch['pbdb']].encode('utf-8'))
					else:
						noMatch = True

					# PBDB Taxon Matches
					if hit['_source'][taxonMatch['pbdb']] is not None:

						idbMatchList.append({"match": {taxonMatch['idigbio']: hit['_source'][taxonMatch['pbdb']]}})
						pbdbMatchList.append({"match": {taxonMatch['pbdb']: hit['_source'][taxonMatch['pbdb']]}})
						data['matchFields'][taxonMatch['pbdb']] = hit['_source'][taxonMatch['pbdb']]
						recHash.update(data['matchFields'][taxonMatch['pbdb']])
					else:
						noMatch = True

					# PBDB Chrono matching ( uses chronolookup index in ES )
					matchChrono = []
					chronoQuery = {
						"query": {
							"bool": {
								"must": [
									{ "range": { "start_ma": { "gte": hit['_source']['max_ma'] } } },
									{ "range": { "end_ma": { "lte": hit['_source']['min_ma'] } } },
									{ "match": { "level": chronoMatchLevel } }
								]
							}
						}
					}

					chronoRes = self.es.search(index="chronolookup", body=chronoQuery)

					for chrono in chronoRes['hits']['hits']:
						matchChrono.append(chrono['_source']['name'])

					data['matchFields']['chronostratigraphy'] = matchChrono

					if not matchChrono:
						noMatch = True

					pbdbMatchList.append({"range": {"min_ma": {"lte": hit['_source']['max_ma']}}})
					pbdbMatchList.append({"range": {"max_ma": {"gte": hit['_source']['min_ma']}}})

					recHash.update( str(matchChrono) )

					linkID = hit['_source']['occurrence_no']
					linkField = 'occurrence_no'

					linkQuery = {
						"size": 10,
						"query": {
							"bool": {
								"must": idbMatchList,
								"should": [
									{ "terms": { chronoMatch['idigbio']['early']: matchChrono}},
									{ "terms": { chronoMatch['idigbio']['late']: matchChrono}}
								]
							}
						}
					}
					queryIndex = 'idigbio'

				#matches['search_after'] = json.dumps(hit["sort"])
				hashRes = recHash.hexdigest()

				if hashRes in matches['results']:
					sourceRow = self.resolveReference(hit["_source"], hit["_id"], hit["_type"], pbdbType)
				else:
					# Resolve Reference, hardset the pbdb_type to refs
					sourceRow = self.resolveReference(hit["_source"], hit["_id"], hit["_type"], pbdbType)
					matches['results'][hashRes] = {'fields': data['matchFields'], 'totalMatches': 0, 'matches': None, 'sources': [sourceRow], 'fullMatchQuery': None}
					if noMatch is False:
						linkResult = self.es.search(index=queryIndex, body=linkQuery)
						totalMatches = linkResult['hits']['total']
						if totalMatches > 0:
							matches['results'][hashRes]['matches'] = []
							for link in linkResult['hits']['hits']:
								row = self.resolveReference(link['_source'], link['_id'], link['_type'], pbdbType)
								if returnMedia and link['_type'] == 'idigbio' and row['idigbio:hasImage'] == 'true':
									mediaFiles = self._queryMedia(row['idigbio:uuid'], row['idigbio:mediarecords'])
									if mediaFiles:
										if mediaOnly:
											mediaMatches['mediaURLs'].append({"record": "https://www.idigbio.org/portal/records/" + row['idigbio:uuid'], "media": mediaFiles})
											#mediaMatches['mediaURLs'].extend(mediaFiles)
										else:
											sourceRow['mediaURLs'] = mediaFiles
								if not mediaOnly:
									row['score'] = link['_score']
									row['type'] = link['_type']
									matches['results'][hashRes]['matches'].append(row)
									data['links'].append([link['_id'], link['_score'], link['_type']])

							if not mediaOnly:
								matches['results'][hashRes]['totalMatches'] = totalMatches
								linkQuery['size'] = totalMatches
								matches['results'][hashRes]['fullMatchQuery'] = json.dumps(linkQuery)

						if not mediaOnly:
							matches['results'][hashRes]['fields'] = data['matchFields']

					if not mediaOnly:
						if queryIndex == 'idigbio':
							sourceQuery = {
								"query":{
									"bool":{
										"must": pbdbMatchList
									}
								}
							}

						elif queryIndex == 'pbdb':
							sourceQuery = {
								"query":{
									"bool":{
										"must": idbMatchList
									}
								}
							}

						matches['results'][hashRes]['fullSourceQuery'] = json.dumps(sourceQuery)

				if returnMedia and hit['_type'] == 'idigbio' and sourceRow['idigbio:hasImage'] == 'true':
					mediaFiles = self._queryMedia(sourceRow['idigbio:uuid'], sourceRow['idigbio:mediarecords'])
					if mediaFiles:
						if mediaOnly:
							mediaMatches['mediaURLs'].append({"record": "https://www.idigbio.org/portal/records/" + sourceRow['idigbio:uuid'], "media": mediaFiles})
							#mediaMatches['mediaURLs'].extend(mediaFiles)
						else:
							sourceRow['mediaURLs'] = mediaFiles
				if not mediaOnly:
					matches['results'][hashRes]['sources'].append(sourceRow)

				if mediaOnly:
					continue

				if hit["_type"] == 'idigbio':
					sourceType = 'idigbio'
					matchType = 'pbdb'
				else:
					sourceType = 'pbdb'
					matchType = 'idigbio'

				matches['results'][hashRes]['sourceType'] = sourceType
				matches['results'][hashRes]['matchType'] = matchType

		if mediaOnly == True:
			mediaMatches['queryInfo'] = {'matchCriteria': {'chronostratigraphyMatch': chronoMatch, 'taxonomyMatch': taxonMatch, 'localityMatch': localityMatch}, 'total': len(mediaMatches['mediaURLs'])}
			return mediaMatches
		matches['queryInfo'] = {'idigbioTotal': idbRes['hits']['total'], 'pbdbTotal': pbdbRes['hits']['total'], 'matchCriteria': {'chronostratigraphyMatch': chronoMatch, 'taxonomyMatch': taxonMatch, 'localityMatch': localityMatch}}
		return matches


"""3D Plot of the data. Each class is represented using a different
color.

Usage:
  train.py [-c <n>]
  train.py -h | --help

Options:
  -c <n>        Number of classes to train [default: 5]
  -o <file>     Output filename
  -h --help     Show this screen.

"""
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from docopt import docopt
from models.utils import load_data, to_classes

if __name__ == '__main__':
    opts = docopt(__doc__)
    nclasses = int(opts['-c'])

    data_len, weeks, ts, xs = load_data()

    a, b, c = (1, 2, 3)
    x = xs[:, a]
    y = xs[:, b]
    z = xs[:, c]
    c = to_classes(ts, nclasses=nclasses)
    c = -c  # Reverse the colors

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    ax.scatter(x, y, z, c=c)
    plt.show()


# -*- coding: utf-8 -*-
import logging
import tensorflow as tf

def get_logger(filename):
    logger = logging.getLogger('logger')
    logger.setLevel(logging.DEBUG)
    logging.basicConfig(format='%(message)s', level=logging.DEBUG)
    handler = logging.FileHandler(filename)
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s: %(message)s'))
    logging.getLogger().addHandler(handler)
    return logger

def focal_loss(logits, labels, alpha, batch_size, epsilon=1.e-7, gamma=2.0):
    """
    样本不均衡考虑的损失函数
    """
    # (Class ,1)
    alpha = tf.constant(alpha, dtype=tf.float32)

    labels = tf.cast(labels, dtype=tf.int32)
    logits = tf.cast(logits, tf.float32)
    # (N,Class) > N*Class
    softmax = tf.reshape(tf.nn.softmax(logits), [-1])
    # (N,) > (N,) ,但是数值变换了，变成了每个label在N*Class中的位置
    labels_shift = tf.range(0, batch_size) * logits.shape[1] + labels
    # labels_shift = tf.range(0, batch_size*32) * logits.shape[1] + labels
    # (N*Class,) > (N,)
    prob = tf.gather(softmax, labels_shift)
    # 预防预测概率值为0的情况  ; (N,)
    prob = tf.clip_by_value(prob, epsilon, 1. - epsilon)
    # (Class ,1) > (N,)
    alpha_choice = tf.gather(alpha, labels)
    # (N,) > (N,)
    weight = tf.pow(tf.subtract(1., prob), gamma)
    weight = tf.multiply(alpha_choice, weight)
    # (N,) > 1
    loss = -tf.reduce_mean(tf.multiply(weight, tf.log(prob)))
    return loss


from typing import List

class Solution:
    def subarraysDivByK(self, nums: List[int], k: int) -> int:
        ans = 0
        prefix_mod = 0
        mod_groups = [0] * k
        mod_groups[0] = 1

        for num in nums:
            prefix_mod = (prefix_mod + num % k + k) % k
            ans += mod_groups[prefix_mod]
            mod_groups[prefix_mod] += 1

        return ans

if __name__ == "__main__":
    assert Solution().subarraysDivByK(nums=[4, 5, 0, -2, -3, 1], k=5) == 7
    assert Solution().subarraysDivByK(nums=[5], k=9) == 0


from rest_framework import permissions

from rest_framework import permissions

class UserPermissionOnViewSet(permissions.BasePermission):

    def has_permission(self, request, view):
        if view.action == 'list':
            return request.user.is_authenticated() and request.user.is_admin
        elif view.action == 'create':
            return True
        elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
            return True
        else:
            return False

    def has_object_permission(self, request, view, obj):
        # Deny actions on objects if the user is not authenticated
        if not request.user.is_authenticated():
            return False

        if view.action == 'retrieve':
            return obj == request.user or request.user.is_admin
        elif view.action in ['update', 'partial_update']:
            return obj == request.user or request.user.is_admin
        elif view.action == 'destroy':
            return request.user.is_admin
        else:
            return False

class UserPermissionOnAPIView(permissions.BasePermission):

    def has_permission(self, request, view):

        if request.method == 'GET':
            return request.user.is_authenticated
        elif request.method == 'POST':
            return True
        elif request.method in ['PUT', 'PATCH']:
            return True
        else:
            return False

    def has_object_permission(self, request, view, obj):
        # Deny actions on objects if the user is not authenticated
        if not request.user.is_authenticated:
            return False

        if request.method == 'GET':
            return obj == request.user
        elif request.method in ['PUT', 'PATCH']:
            return obj == request.user
        else:
            return False


#plotting
import sn_analytic
import matplotlib
import matplotlib.pyplot as plt
matplotlib.pyplot.ioff()

#to avoid reloading models
#need to set some constant a  = plots.initialise(), then include a as an argument in 	plotting function
def initialise():
    s = sn_analytic.SN()
    p = s.dumps
    return p

def plotting(p, eta_outflow = None, threshold = None, zeta = None):

	if not zeta:
		for i in range(10):
		 zeta = 0.20 + 0.01*i
		 s = sn_analytic.SN(p)
		 s.plotsave(zeta = zeta,
				eta_outflow = eta_outflow,
				threshold = threshold,
				)
		 print("plotted for zeta = {}".format(zeta))
		 filename = 'z{}_eo{}_t{}'.format(round(zeta,2),eta_outflow,threshold)
		 plt.savefig(filename, format='png')
		 plt.close()

	if not eta_outflow:
		for i in range(61):
		 eta_outflow = 0.30 + 0.01*i
		 s = sn_analytic.SN(p)
		 s.plotsave(zeta = zeta,
				eta_outflow = eta_outflow,
				threshold = threshold,
				)
		 print("plotted for eta_outflow = {}".format(eta_outflow))
		 filename = 'z{}_eo{}_t{}'.format(round(zeta,2),round(eta_outflow,2),round(threshold,2))
		 plt.savefig(filename, format='png')
		 plt.close()

	if not threshold:
		for i in range():
		 threshold = 0.60 + 0.01*i
		 s = sn_analytic.SN(p)
		 s.plotsave(zeta = zeta,
				eta_outflow = eta_outflow,
				threshold = threshold,
				)
		 print("plotted for threshold = {}".format(threshold))
		 filename = 'z{}_eo{}_t{}'.format(round(zeta,2),round(eta_outflow,2),round(threshold,2))
		 plt.savefig(filename, format='png')
		 plt.close()


from pathlib import Path

from layoutlm_utils.image import extract_metadata_from_images

def main(images_paths: list[Path]):
    metadata = extract_metadata_from_images(images_paths)
    print(metadata)

if "__main__" == __name__:
    images_paths = [
        Path(
            "/label_studio/dummy_example/labelstudio_result/parsed/img/91c642d0-invoice_image.jpg"),
        Path(
            "/label_studio/dummy_example/labelstudio_result/parsed/img/744dad0e-page_12.jpg")]
    main(images_paths)


"""
Unit tests for the generic (shared) components of the SRI Testing Framework
"""
from typing import  Dict
from sys import stderr

import logging

from json import dump

from copy import deepcopy

import pytest

from dictdiffer import diff

from reasoner_validator.trapi import TRAPI_1_3_0, TRAPI_1_4_2
from reasoner_validator.validator import TRAPIResponseValidator
from reasoner_validator.report import TRAPIGraphType

from tests import PATCHED_140_SCHEMA_FILEPATH, SAMPLE_NODES_WITH_ATTRIBUTES
from tests.test_validation_report import check_messages

logger = logging.getLogger(__name__)
logger.setLevel("DEBUG")

_TEST_QG_1 = {
    "nodes": {
        "type-2 diabetes": {"ids": ["MONDO:0005148"]},
        "drug": {
            "categories": ["biolink:Drug"]
        }
    },
    "edges": {
        "treats": {
            "subject": "drug",
            "predicates": ["biolink:treats"],
            "object": "type-2 diabetes"
        }
    }
}

# Sample edge 1
_TEST_EDGES_1 = {
       "edge_1": {
           "subject": "NCBIGene:29974",
           "predicate": "biolink:physically_interacts_with",
           "object": "PUBCHEM.COMPOUND:597",
           "attributes": [
               {
                   "attribute_source": "infores:hmdb",
                   "attribute_type_id": "biolink:primary_knowledge_source",
                   "attributes": [],
                   "description": "MolePro's HMDB target transformer",
                   "original_attribute_name": "biolink:primary_knowledge_source",
                   "value": "infores:hmdb",
                   "value_type_id": "biolink:InformationResource"
               },
               {
                   "attribute_source": "infores:molepro",
                   "attribute_type_id": "biolink:aggregator_knowledge_source",
                   "attributes": [],
                   "description": "Molecular Data Provider",
                   "original_attribute_name": "biolink:aggregator_knowledge_source",
                   "value": "infores:molepro",
                   "value_type_id": "biolink:InformationResource"
               }
            ],
        }
    }

_TEST_KG_1 = {
    "nodes": SAMPLE_NODES_WITH_ATTRIBUTES,
    "edges": _TEST_EDGES_1
}

_TEST_RESULTS_1 = [
        {
            "node_bindings": {
                "type-2 diabetes": [{"id": "MONDO:0005148"}],
                "drug": [{"id": "ncats.drug:9100L32L2N"}]
            },
            "edge_bindings": {
                "treats": [{"id": "df87ff82"}]
            }
        }
    ]

# Sample edge 2
_TEST_EDGES_2 = {
       "edge_1": {
           "subject": "NCBIGene:29974",
           "predicate": "biolink:physically_interacts_with",
           "object": "PUBCHEM.COMPOUND:597",
           "attributes": [
               {
                   "attribute_source": "infores:hmdb",
                   "attribute_type_id": "biolink:aggregator_knowledge_source",
                   "attributes": [],
                   "description": "Molecular Data Provider",
                   "original_attribute_name": "biolink:aggregator_knowledge_source",
                   "value": "infores:molepro",
                   "value_type_id": "biolink:InformationResource"
               }
           ],
        }
    }

_TEST_KG_2 = {
    "nodes": SAMPLE_NODES_WITH_ATTRIBUTES,
    "edges": _TEST_EDGES_2
}

_TEST_QG_2 = {
    "nodes": {
        "paper": {
            "categories": ["biolink:InformationContentEntity"]
        },
        "author": {
            "ids": ["ORCID:0000-0002-4447-5978"]
        }
    },
    "edges": {
        "citation": {
            "subject": "paper",
            "predicates": ["biolink:contributor"],
            "object": "author"
        }
    }
}

_TEST_NODES_2 = {
        "PMID:11156626": {
            "name": "A SNP resource for human chromosome 22: " +
                    "extracting dense clusters of SNPs from the genomic sequence",
            "categories": [
                "biolink:InformationContentEntity"
            ],
        },
        "ORCID:0000-0002-4447-5978": {
            "categories": [
                "biolink:AdministrativeEntity"
            ]
        }
    }

# Sample edge 3
_TEST_EDGES_3 = {
       "edge_1": {
           "subject": "PMID:11156626",
           "predicate": "biolink:contributor",
           "object": "ORCID:0000-0002-4447-5978",
           "attributes": [
               {
                   "attribute_type_id": "biolink:primary_knowledge_source",
                   "value": "infores:automat-text-mining-provider"
               }
           ],
        }
    }

_TEST_KG_3 = {
    "nodes": _TEST_NODES_2,
    "edges": _TEST_EDGES_3
}

_TEST_RESULTS_2 = [
        {
            "node_bindings": {
                "paper": [{"id": "PMID:11156626"}],
                "author": [{"id": "ORCID:0000-0002-4447-5978"}]
            },
            "edge_bindings": {
                "citation": [{"id": "edge1"}]
            }
        }
    ]

# Sample edge 2
_TEST_EDGES_4 = {
       "edge_1": {
           "subject": "NCBIGene:29974",
           "predicate": "biolink:physically_interacts_with",
           "object": "PUBCHEM.COMPOUND:597",
           "attributes": [
               {
                   "attribute_type_id": "biolink:aggregator_knowledge_source",
                   "value": "infores:molepro"
               },
               {
                   "attribute_type_id": "biolink:primary_knowledge_source",
                   "value": "infores:automat-text-mining-provider"
               },
               {
                   "attribute_type_id": "biolink:primary_knowledge_source",
                   "value": "infores:hmdb"
               }
           ],
        }
    }

_TEST_KG_4 = {
    "nodes": SAMPLE_NODES_WITH_ATTRIBUTES,
    "edges": _TEST_EDGES_4
}

# From Implementation Guidelines circa June 2023
_TEST_TRAPI_1_4_2_FULL_SAMPLE = {
    "message": {
        "query_graph": {
            "nodes": {
                "type-2 diabetes": {"ids": ["MONDO:0005148"]},
                "drug": {"categories": ["biolink:Drug"]}
            },
            "edges": {
                "treats": {"subject": "drug", "predicates": ["biolink:treats"],
                           "object": "type-2 diabetes"}
            }
        },
        "knowledge_graph": {
            "nodes": {
                "MONDO:0005148": {"name": "type-2 diabetes", "categories": ["biolink:Disease"]},
                "ncats.drug:9100L32L2N": {"name": "metformin", "categories": ["biolink:Drug"]}
            },
            "edges": {
                "df87ff82": {
                    "subject": "ncats.drug:9100L32L2N",
                    "predicate": "biolink:treats",
                    "object": "MONDO:0005148",
                    "sources": [
                        {
                            "resource_id": "infores:chebi",
                            "resource_role": "primary_knowledge_source",
                            "upstream_resource_ids": []
                        },
                        {
                            "resource_id": "infores:biothings-explorer",
                            "resource_role": "aggregator_knowledge_source",
                            "upstream_resource_ids": [
                                "infores:chebi"
                            ]
                        },
                        {
                            "resource_id": "infores:molepro",
                            "resource_role": "aggregator_knowledge_source",
                            "upstream_resource_ids": [
                                "infores:biothings-explorer"
                            ]
                        },
                        {
                            "resource_id": "infores:arax",
                            "resource_role": "aggregator_knowledge_source",
                            "upstream_resource_ids": [
                                "infores:molepro"
                            ]
                        }
                    ]
                }
            }
        },
        "auxiliary_graphs": {
            "a0": {
                "edges": [
                    "e02",
                    "e12"
                ]
            },
            "a1": {
                "edges": [
                    "extra_edge0"
                ]
            },
            "a2": {
                "edges": [
                    "extra_edge1"
                ]
            }
        },
        "results": [
            {
                "node_bindings": {
                    "type-2 diabetes": [{"id": "MONDO:0005148"}],
                    "drug": [{"id": "ncats.drug:9100L32L2N"}]
                },
                "analyses": [
                    {
                        "resource_id": "infores:ara0",
                        "edge_bindings": {"treats": [{"id": "df87ff82"}]},
                        "support_graphs": [],
                        "score": 0.7
                    }
                ]
            }
        ]
    }
}

_TEST_TRAPI_1_4_2_FULL_SAMPLE_WITHOUT_AUX_GRAPH = deepcopy(_TEST_TRAPI_1_4_2_FULL_SAMPLE)
_TEST_TRAPI_1_4_2_FULL_SAMPLE_WITHOUT_AUX_GRAPH["message"].pop("auxiliary_graphs")

# original TRAPI schema.. changing the 'schema_version' may generate errors
_TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_SCHEMA_VERSION = deepcopy(_TEST_TRAPI_1_4_2_FULL_SAMPLE)
_TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_SCHEMA_VERSION["schema_version"] = "1.3.0"

# original TRAPI schema.. changing the 'biolink_version' may generate errors
_TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_BIOLINK_VERSION = deepcopy(_TEST_TRAPI_1_4_2_FULL_SAMPLE)
_TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_BIOLINK_VERSION["biolink_version"] = "2.4.8"

NUM_SAMPLE_NODES = 5

SAMPLE_NODES: Dict = dict()
for node_id in range(1, NUM_SAMPLE_NODES):
    SAMPLE_NODES[f"n{node_id}"] = dict()

SAMPLE_EDGES: Dict = dict()
for subject_id in SAMPLE_NODES:
    for object_id in SAMPLE_NODES:
        if subject_id != object_id:
            SAMPLE_EDGES[f"e{subject_id}{object_id}"] = {
                "subject": subject_id,
                "predicate": "biolink:related_to",
                "object": object_id
            }

TEST_GRAPH: Dict = {
    "nodes": SAMPLE_NODES,
    "edges": SAMPLE_EDGES
}

# this unit test checks that the original response object is returned verbatim
def test_conservation_of_response_object():
    validator: TRAPIResponseValidator = TRAPIResponseValidator()
    input_response = deepcopy(_TEST_TRAPI_1_4_2_FULL_SAMPLE)
    reference_response = deepcopy(_TEST_TRAPI_1_4_2_FULL_SAMPLE)
    assert input_response == reference_response
    validator.check_compliance_of_trapi_response(response=input_response)
    assert not list(diff(input_response, reference_response))

@pytest.mark.parametrize(
    "edges_limit,number_of_nodes_returned,number_of_edges_returned",
    [
        (   # Query 0 - unlimited sample whole graph
            0,  # edges_limit
            len(SAMPLE_NODES),  # number of nodes returned
            len(SAMPLE_EDGES)   # number of edges returned
        ),
        (   # Query 1 - sample just 2 edges
            2,  # edges_limit
            3,  # number of nodes returned
            2   # number of edges returned
        ),
        (   # Query 2 - sample just edge_value is negative number (functionally equivalent to zero)
            -1,  # edges_limit
            len(SAMPLE_NODES),  # number of nodes returned
            len(SAMPLE_EDGES)   # number of edges returned
        )
    ]
)
def test_sample_graph(edges_limit: int, number_of_nodes_returned: int, number_of_edges_returned: int):
    validator: TRAPIResponseValidator = TRAPIResponseValidator()
    kg_sample: Dict = validator.sample_graph(graph=TEST_GRAPH, edges_limit=edges_limit)
    assert kg_sample
    assert len(kg_sample["nodes"]) == number_of_nodes_returned
    assert len(kg_sample["edges"]) == number_of_edges_returned

@pytest.mark.parametrize(
    "response,trapi_version,biolink_version,target_provenance,strict_validation,message",
    [
        (   # Query 0 - Completely empty Response.Message
            {
                "message": {

                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: ERROR - Response returned an empty Message Query Graph!"
            "error.trapi.response.message.empty"
        ),
        (   # Query 1 - Response.Message also devoid of content, missing QGraph trapped first....
            {
                "message": {
                    "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: ERROR - TRAPI Message is missing its Query Graph!"
            "error.trapi.response.query_graph.missing"
        ),
        (   # Query 2 - Response.Message also devoid of content, null QGraph trapped first....
            {
                "message": {
                    "query_graph": None,
                    "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: ERROR - Response returned a null or empty Message Query Graph!"
            "error.trapi.response.query_graph.empty"
        ),
        (
            # Query 3 - Partly empty Response.Message with a modest but
            #           workable query graph? Missing KG trapped next?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    # "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: ERROR - TRAPI Message is missing its Knowledge Graph component?"
            "error.trapi.response.knowledge_graph.missing"
        ),
        (
            # Query 4 - Partly empty Response.Message with a modest
            #           but workable query graph? Empty KG trapped next?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: WARNING - Response returned an empty Message Knowledge Graph?"
            "warning.trapi.response.knowledge_graph.empty"
        ),
        (
            # Query 5 - Partly empty Response.Message with a modest but workable
            #           query and knowledge graphs? Missing Results detected next?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    # "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: ERROR - TRAPI Message is missing its Results component!"
            "error.trapi.response.results.missing"
        ),
        (
            # Query 6 - Partly empty Response.Message with a modest but workable query and
            #           knowledge graphs? Null valued Results detected next - just issue a warning?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: WARNING -Response returned empty Message.results?"
            "warning.trapi.response.results.empty"
        ),
        (
            # Query 7 - Partly empty Response.Message with a modest but workable
            #           query and knowledge graphs? Non-array Results detected next?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": {"invalid results"}
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: ERROR - Response returned a non-array Message.Results!
            "error.trapi.response.results.not_array"
        ),
        (
            # Query 8 - Partly empty Response.Message with a modest but workable query and
            #           knowledge graphs? Empty Results detected next - just issue a warning?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": []
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            # "Validate TRAPI Response: ERROR - Response returned empty Message.results?"
            "warning.trapi.response.results.empty"
        ),
        (
            # Query 9 - Full Message, without "sources" and "strict_validation": False - should pass?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (
            # Query 10 - Full Message, with strict validation - still passes
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            ""
        ),
        (
            # Query 11 - Full Message, with "strict validation" and non-null sources" that match
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            {
                "ara_source": None,
                "kp_source": "infores:hmdb",
                "kp_source_type": "primary"
            },
            True,
            ""
        ),
        (
            # Query 12 - Full Message, with strict validation and a non-null kp_source_type that doesn't match
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            {
                "ara_source": None,
                "kp_source": "infores:molepro",
                "kp_source_type": "primary"
            },
            True,
            "warning.knowledge_graph.edge.provenance.kp.missing"
        ),
        (
            # Query 13 - Full Message, with strict validation and a non-null ara_source that doesn't match
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            {
                "ara_source": "infores:aragorn",
                "kp_source": "infores:hmdb",
                "kp_source_type": "primary"
            },
            True,
            "warning.knowledge_graph.edge.provenance.ara.missing"
        ),
        (
            # Query 14 - Full Message, with "strict validation" and a non-null "sources" data that matches
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            {
                "ara_source": "infores:molepro",
                "kp_source": "infores:hmdb",
                "kp_source_type": "primary"
            },
            True,
            ""
        ),
        (
            # Query 15 - Full Message, with "strict validation" and a non-null "sources" KP that matches
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            {
                "ara_source": None,
                "kp_source": "infores:molepro",
                "kp_source_type": "aggregator"
            },
            True,
            ""
        ),
        (
            # Query 16 - Full Message, with strict validation and
            #            a non-null kp_source_type results in missing primary
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_2,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            {
                "ara_source": None,
                "kp_source": "infores:molepro",
                "kp_source_type": "aggregator"
            },
            True,
            "error.knowledge_graph.edge.provenance.missing_primary"
        ),
        (
            # Query 17 - Full Message, with strict validation and
            #            non-null kp_source_type results, has multiple "primary knowledge sources"
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_4,
                    "results": _TEST_RESULTS_1
                }
            },
            TRAPI_1_3_0,
            None,
            {
                "ara_source": None,
                "kp_source": "infores:molepro",
                "kp_source_type": "aggregator"
            },
            True,
            "warning.knowledge_graph.edge.provenance.multiple_primary"
        ),
        (
            # Query 18 - Full Message, with non-strict validation.
            #            Both knowledge graph nodes have "mixin" categories,
            #            the list of categories for knowledge graphs
            #            must have at least one concrete category,
            #            hence, a validation error is now reported:
            {
                "message": {
                    "query_graph": _TEST_QG_2,
                    "knowledge_graph": _TEST_KG_3,
                    "results": _TEST_RESULTS_2
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            "error.knowledge_graph.node.categories.not_concrete"
        ),
        (
            # Query 19 - Full Message, WITH strict validation - abstract predicate?
            {
                "message": {
                    "query_graph": _TEST_QG_2,
                    "knowledge_graph": _TEST_KG_3,
                    "results": _TEST_RESULTS_2
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            "error.query_graph.edge.predicate.abstract"
        ),
        (
            # Query 20 - Valid full Message, under strict validation.
            #            Message is valid, but the "workflow" field is not an array?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                },
                "workflow": "workflows-not-an-array"
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            # "Validate TRAPI Response: ERROR - TRAPI schema error: the "workflow" field must be an array"
            "critical.trapi.validation"
        ),
        (
            # Query 21 - Valid full Message, under strict validation.
            #            Message is valid, the "workflow" field is an array,
            #            but the single list entry is an invalid workflow spec?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                },
                "workflow": ["not-a-valid-workflow-spec"]
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            # Validate TRAPI Response: ERROR - TRAPI schema error: the "workflow" field must be an array of
            # a "workflow" JSON objects, with contents as defined by the workflow schema.
            "critical.trapi.validation"
        ),
        (
            # Query 22 - Valid full Message, under strict validation.
            #            Message is valid, the "workflow" field is an array,
            #            but the single list entry is in the workflow schema
            #            and has at least the one required field "id"
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                },
                "workflow": [{"id": "annotate"}]
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            ""   # this simple workflow spec should pass?
        ),
        (
            # Query 23 - Valid full Message, under strict validation. Message is valid, the "workflow" field is array,
            #            but the single list entry is an elaborated "real world" workflow spec,
            #            but one entry overlay_compute_ngd is incomplete - doesn't fully validate!
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                },
                "workflow": [
                    {  # "real" world workflow spec from E. Deutsch
                      "id": "fill",
                      "parameters": {
                        "allowlist": [
                          "infores-rtx-kg2"
                        ]
                      }
                    },
                    {
                      "id": "bind"
                    },
                    {
                      "id": "overlay_compute_ngd",
                      "parameters": {
                        "virtual_relation_label": "ngd1"
                      }
                    },
                    {
                      "id": "score"
                    },
                    {
                      "id": "complete_results"
                    }
                ]
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            # "Validate TRAPI Response: ERROR - TRAPI schema validation error: the "workflow"
            # field entry overlay_compute_ngd is missing a required parameter "qnodes_keys"
            "critical.trapi.validation"
        ),
        (
            # Query 24 - Valid full Message, under strict validation. Message is valid, the "workflow" field is array,
            #            but the single list entry is an elaborated "real world" workflow spec
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                },
                "workflow": [
                    {  # "real" world workflow spec from E. Deutsch
                      "id": "fill",
                      "parameters": {
                        "allowlist": [
                          "infores-rtx-kg2"
                        ]
                      }
                    },
                    {
                      "id": "bind"
                    },
                    {
                      "id": "overlay_compute_ngd",
                      "parameters": {
                        "virtual_relation_label": "ngd1",
                        "qnode_keys": ["type-2 diabetes", "drug"]
                      }
                    },
                    {
                      "id": "score"
                    },
                    {
                      "id": "complete_results"
                    }
                ]
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            ""   # this simple workflow spec should pass?
        ),
        (
            # Query 25 - Valid full Message, under strict validation. Message is valid,
            #            the "workflow" field is an array, but runner_parameters is None.
            #            This is technically invalid, but we have a code patch which should filter it out (for now)
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": _TEST_RESULTS_1
                },
                "workflow": [
                    {
                        "id": "lookup",
                        "runner_parameters": None,
                        "parameters": None
                    }
                ]
            },
            TRAPI_1_3_0,
            None,
            None,
            True,
            # TRAPI Response workflow sanitization restored - this should pass
            ""
        ),
        (   # Query 26 - We throw a full TRAPI JSON example here (taken directly from the
            #            TRAPI implementation guidelines...) just for fun and profit
            _TEST_TRAPI_1_4_2_FULL_SAMPLE,
            TRAPI_1_4_2,
            None,
            None,
            True,
            ""   # this filtered workflow spec should pass
        ),
        (   # Query 27 - We throw a full TRAPI JSON example here (taken directly from the TRAPI implementation
            #            guidelines...) but add the 'schema_version' just for fun and profit
            _TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_SCHEMA_VERSION,
            None,
            "3.0.0",
            None,
            True,
            "critical.trapi.validation"   # trying to validate a 1.4.2 schema against 1.3.0 will fail!
        ),
        (   # Query 28 - We throw a full TRAPI JSON example here (taken directly from the TRAPI implementation
            #            guidelines...) but explicitly specify the 'biolink_version == 2.5.8' just for fun and profit
            _TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_BIOLINK_VERSION,
            TRAPI_1_4_2,
            None,
            None,
            True,
            # Validation with 2.4.8 generates a warning
            "warning.knowledge_graph.edge.predicate.non_canonical"
        )
    ]
)
def test_check_biolink_model_compliance_of_trapi_response(
        response: Dict,
        trapi_version: str,
        biolink_version: str,
        target_provenance: Dict,
        strict_validation: bool,
        message: str
):
    validator: TRAPIResponseValidator = TRAPIResponseValidator(
        trapi_version=trapi_version,
        biolink_version=biolink_version,
        strict_validation=strict_validation,
        target_provenance=target_provenance
    )
    validator.check_compliance_of_trapi_response(response=response)
    check_messages(validator, message, no_errors=True)

@pytest.mark.parametrize(
    "response,trapi_version,biolink_version,sources,strict_validation,code",
    [
        (   # Query 0 - Completely empty Response.Message
            {
                "message": {

                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (   # Query 1 - Response.Message also devoid of content, missing QGraph trapped first....
            {
                "message": {
                    "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (   # Query 2 - Response.Message also devoid of content, null QGraph trapped first....
            {
                "message": {
                    "query_graph": None,
                    "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (
            # Query 3 - Partly empty Response.Message with a modest but
            #           workable query graph? Missing KG trapped next?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    # "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (
            # Query 4 - Partly empty Response.Message with a modest
            #           but workable query graph? Empty KG trapped next?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": None,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (
            # Query 5 - Partly empty Response.Message with a modest but workable
            #           query and knowledge graphs? Missing Results detected next?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    # "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (
            # Query 6 - Partly empty Response.Message with a modest but workable query and
            #           knowledge graphs? Null valued Results detected next - just issue a warning?
            {
                "message": {
                    "query_graph": _TEST_QG_1,
                    "knowledge_graph": _TEST_KG_1,
                    "results": None
                }
            },
            TRAPI_1_3_0,
            None,
            None,
            False,
            ""
        ),
        (
            # Query 7 - Full fake sample Response from TRAPI 1.4.0 implementation guidelines
            _TEST_TRAPI_1_4_2_FULL_SAMPLE,
            # 25 June 2023 1.4.0 trapi_version with
            # defective auxiliary_graphs schema model
            # now temporarily patched?
            TRAPI_1_4_2,
            None,
            None,
            False,
            ""  # would be a "critical.trapi.validation" if the schema was unpatched
        ),
        (
            # Query 8 - Full fake sample Response from TRAPI 1.4.0 implementation guidelines
            _TEST_TRAPI_1_4_2_FULL_SAMPLE,
            # patched 1.4.0 test schema - fixed critical
            # TRAPI schema parsing error with auxiliary_graphs
            PATCHED_140_SCHEMA_FILEPATH,
            None,
            None,
            False,
            ""
        ),
        (
            # Query 9 - Sample Response from TRAPI 1.4.0 implementation guidelines without auxiliary_graph
            _TEST_TRAPI_1_4_2_FULL_SAMPLE_WITHOUT_AUX_GRAPH,
            # 25 June 2023 1.4.0 trapi_version with
            # defective auxiliary_graphs schema model
            TRAPI_1_4_2,
            None,
            None,
            False,
            ""  # nullable: true allows this outcome
        ),
        (
            # Query 10 - Sample Response from TRAPI 1.4.0 implementation guidelines without auxiliary_graph
            _TEST_TRAPI_1_4_2_FULL_SAMPLE_WITHOUT_AUX_GRAPH,
            # patched 1.4.0 test schema - fixed critical
            # TRAPI schema parsing error with auxiliary_graphs
            PATCHED_140_SCHEMA_FILEPATH,
            None,
            None,
            False,
            ""  # should still work if nullable: true
        )
    ]
)
def test_check_biolink_model_compliance_of_trapi_response_suppressing_empty_data_warnings(
        response, trapi_version, biolink_version, sources, strict_validation, code
):
    validator: TRAPIResponseValidator = TRAPIResponseValidator(
        trapi_version=trapi_version,
        biolink_version=biolink_version,
        target_provenance=sources,
        strict_validation=strict_validation,
        suppress_empty_data_warnings=True
    )
    validator.check_compliance_of_trapi_response(response=response)
    check_messages(validator, code, no_errors=True)

_TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_REPORTABLE_ERRORS = deepcopy(_TEST_TRAPI_1_4_2_FULL_SAMPLE)
sample_message = _TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_REPORTABLE_ERRORS["message"]
sample_qgraph = sample_message["query_graph"]
sample_kg = sample_message["knowledge_graph"]
sample_kg_node_missing_category = sample_kg["nodes"]["MONDO:0005148"].pop("categories")
sample_kg_edge_missing_node_subject = sample_kg["edges"]["df87ff82"].pop("subject")
sample_kg_edge_abstract_predicate = sample_kg["edges"]["df87ff82"]["predicate"] = "biolink:not_a_predicate"

@pytest.mark.parametrize(
    "response",
    [
        _TEST_TRAPI_1_4_2_FULL_SAMPLE,
        _TEST_TRAPI_1_4_2_FULL_SAMPLE_WITH_REPORTABLE_ERRORS
    ]
)
def test_dump_report_of_biolink_model_compliance_of_trapi_response_with_errors(response: Dict):
    validator: TRAPIResponseValidator = TRAPIResponseValidator()
    validator.check_compliance_of_trapi_response(response=response)
    validator.dump()


from tkinter import *
from PIL import ImageTk,Image
from tkinter import filedialog
from tkinter import messagebox
import sqlite3

root=Tk()
root.geometry('800x790')
root.title("AMS")
root.iconbitmap('asd.ico')

def create():
    conn=sqlite3.connect('PKPDatabase.db')
    c=conn.cursor()
    c.execute("CREATE TABLE IF NOT EXISTS users(id integer primary key autoincrement,Firstname TEXT,Lastname TEXT,Fathername TEXT,Mothername TEXT,Dateofbirth TEXT,Villagename TEXT,Statename TEXT,Countryname TEXT,sqltime TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL)")
    conn.commit()
    conn.close()
create()

#Title of Project
Title=Label(text="      ADHAR MANAGEMENT SYSTEM       ",bd=16,fg="#000000",font=('arial',35,'bold'),bg="OliveDrab1",relief='raise',width=32,height=1)
Title.pack()
SmallTitle=Label(text="Basic Details Form",bd=3,bg="Cyan",width=32,height=1,font=('arial',10,'bold'),relief=SUNKEN)
SmallTitle.place(x=270,y=100)

#Basic Informations

First_Name=Label(root, text="First Name:-", width=20, font=("bold"),fg="Cornflowerblue")
First_Name.place(x=50,y=200)
FNR=StringVar()
First_Name_Box=Entry(root,width=40,bg="honeydew2",textvariable=FNR)
First_Name_Box.place(x=300, y=200)

Last_Name=Label(root, text="Last Name:-  ", width=20, font=("bold"),fg="Cornflowerblue")
Last_Name.place(x=50,y=250)
LNR=StringVar()
Last_Name_Box=Entry(root,width=40,bg="honeydew2",textvariable=LNR)
Last_Name_Box.place(x=300, y=250)

Father_Name=Label(root, text="Father Name:-", width=20, font=("bold"),fg="Cornflowerblue")
Father_Name.place(x=50,y=300)
FFNR=StringVar()
Father_Name_Box=Entry(root,width=40,bg="honeydew2",textvariable=FFNR)
Father_Name_Box.place(x=300, y=300)

Mother_Name=Label(root, text="Mother Name:-", width=20, font=("bold"),fg="Cornflowerblue")
Mother_Name.place(x=50,y=350)
MMNR=StringVar()
Mother_Name_Box=Entry(root,width=40,bg="honeydew2",textvariable=MMNR)
Mother_Name_Box.place(x=300, y=350)

DOB=Label(root, text="Date Of Birth:-", width=20, font=("bold"),fg="Cornflowerblue")
DOB.place(x=50,y=400)
DOBR=StringVar()
DOB_Box=Entry(root,width=40,bg="honeydew2",textvariable=DOBR)
DOB_Box.place(x=300, y=400)

Religion=Label(root, text="Religion:-", width=20, font=("bold"),fg="Cornflowerblue")
Religion.place(x=50,y=450)
var=IntVar()
Radiobutton(root,text="Hindu",variable=var,value=1,bg="green yellow").place(x=300,y=450)
Radiobutton(root,text="Muslim",variable=var,value=2,bg="green yellow").place(x=370,y=450)
Radiobutton(root,text="Sikhs",variable=var,value=3,bg="green yellow").place(x=440,y=450)
Radiobutton(root,text="Christian",variable=var,value=4,bg="green yellow").place(x=500,y=450)

Gender=Label(root, text="Gender:-", width=20, font=("bold"),fg="Cornflowerblue")
Gender.place(x=50,y=500)
GenderList=['Male','Female','Other']
c=StringVar()
d=OptionMenu(root,c,*GenderList)
c.set("Select Gender")
d.place(x=300,y=500)

Language=Label(root, text="Language:-", width=20, font=("bold"),fg="Cornflowerblue")
Language.place(x=50,y=550)
v1=IntVar()
Checkbutton(root, text="Hindi", variable=v1,bg="pale green1").place(x=300,y=550)
v2=IntVar()
Checkbutton(root, text="English", variable=v2,bg="pale green1").place(x=370,y=550)
v3=IntVar()
Checkbutton(root, text="Sanskrit", variable=v3,bg="pale green1").place(x=440,y=550)
v4=IntVar()
Checkbutton(root, text="Urdu", variable=v4,bg="pale green1").place(x=520,y=550)

Village=Label(root, text="Village Name:-", width=20, font=("bold"),fg="Cornflowerblue")
Village.place(x=50,y=600)
VNBR=StringVar()
Village_Box=Entry(root,width=40,bg="wheat1",textvariable=VNBR)
Village_Box.place(x=300, y=600)

State=Label(root, text="State Name:-", width=20, font=("bold"),fg="Cornflowerblue")
State.place(x=50,y=650)
SNBR=StringVar()
State_Box=Entry(root,width=40,bg="wheat1",textvariable=SNBR)
State_Box.place(x=300, y=650)

Country=Label(root, text="Country Name:-", width=20, font=("bold"),fg="Cornflowerblue")
Country.place(x=50,y=700)
CNBR=StringVar()
Country_Box=Entry(root,width=40,bg="wheat1",textvariable=CNBR)
Country_Box.place(x=300, y=700)

#First Windows-------------------------------------------------------------------------------------------
def ImageWindows():
    top1=Toplevel()
    top1.geometry('500x500')
    top1.title("Image Windows")
    PassportSI = Label(top1, text="Passport Size Image:-", width=20, font=("bold"), fg="Cornflowerblue")
    PassportSI.place(x=5, y=5)
    def OpenImage():
        global my_image
        top1.filename = filedialog.askopenfilename(initialdir="D:\Tkinter\Python\TkinterPFiles", title="Select A Image",
        filetypes=(("PNG Image", "*.png"), ("All Image", "*.*")))

        my_image = ImageTk.PhotoImage(Image.open(top1.filename))
        my_image_label = Label(top1,image=my_image).place(x=100,y=70)
    my_btn = Button(top1,text="Select Image", command=OpenImage).place(x=250, y=7)

    btnC=Button(top1,text="Close Windows",bg="firebrick1",fg="Black",command=top1.destroy).place(x=200,y=470)
btn1=Button(root,text="Image Section",bg="dark orange",fg="Black",command=ImageWindows).place(x=10,y=750)

#Second Windows-------------------------------------------------------------------------------------------
def DevelopersWindows():
    top2=Toplevel()
    top2.title("Developers Windows")
    global my_img
    my_img = ImageTk.PhotoImage(Image.open("madeby.png"))
    my_label = Label(top2,image=my_img).pack()

    btnC=Button(top2,text="Close Windows",bg="firebrick1",fg="Black",command=top2.destroy).place(x=520,y=620)
btn2=Button(root,text="Developers Details",bg="dark orange",fg="Black",command=DevelopersWindows).place(x=690,y=750)

#Third Windows-------------------------------------------------------------------------------------------
def BMICheck():
    top3=Toplevel()
    top3.geometry("1350x650+0+0")
    top3.resizable(0, 0)
    top3.title("BMI")

    def BMI_Cal():
        BHeight = float(var2.get())
        BWeight = float(var1.get())
        BMI = str('%.2f' % (BWeight / (BHeight * BHeight)))
        lblBMIResult.config(text=BMI)

    var1 = DoubleVar()
    var2 = DoubleVar()

    Tops = Frame(top3, width=1350, height=50, bd=8, relief="raise")
    Tops.pack(side=TOP)
    f1 = Frame(top3, width=600, height=600, bd=8, relief="raise")
    f1.pack(side=LEFT)
    f2 = Frame(top3, width=300, height=700, bd=8, relief="raise")
    f2.pack(side=RIGHT)

    f1a = Frame(f1, width=600, height=200, bd=20, relief="raise")
    f1a.pack(side=TOP)
    f1b = Frame(f1, width=600, height=600, bd=20, relief="raise")
    f1b.pack(side=TOP)

    lblTitle = Label(Tops, text="          Body Mass Index        ", padx=16, pady=16, bd=16,
                     fg="#000000", font=('arial', 54, 'bold'),
                     bg="spring green", relief='raise', width=32, height=1)
    lblTitle.pack()

    lblWeight = Label(f1a, text="Select Weight in Kilograms ", font=('arial', 20, 'bold'), bd=20).grid(row=0, column=0)
    Bodyweight = Scale(f1a, variable=var1, from_=1, to=500, length=880, tickinterval=30, orient=HORIZONTAL)
    Bodyweight.grid(row=1, column=0)

    lblheight = Label(f1b, text="Enter Height in Meters Square", font=('arial', 20, 'bold'), bd=20).grid(row=0,
                                                                                column=0)
    txtheight = Entry(f1b, textvariable=var2, font=('arial', 16, 'bold'), bd=16, width=22, justify='center')
    txtheight.grid(row=1, column=0)

    lblBMIResult = Label(f1b, padx=16, pady=16, bd=16,
                         fg="#000000", font=('arial', 30, 'bold'),
                         bg="hot pink", relief='sunk', width=34, height=1)
    lblBMIResult.grid(row=2, column=0)

    lblBMITable = Label(f2, font=('arial', 20, 'bold'), text="BMI Table").grid(row=0, column=0)
    txtlblBMITable = Text(f2, height=12, width=38, bd=16, font=('arial', 12, 'bold'))
    txtlblBMITable.grid(row=1, column=0)

    txtlblBMITable.insert(END, 'Under weight \t\t' + "<19\n\n")
    txtlblBMITable.insert(END, 'Normal weight \t\t' + "19-24,9\n\n")
    txtlblBMITable.insert(END, 'Overweight \t\t' + "25-29,9\n\n")
    txtlblBMITable.insert(END, 'Obesity level I \t\t' + "30-34,9\n\n")
    txtlblBMITable.insert(END, 'Obesity level II\t\t' + "35-39,9\n\n")
    txtlblBMITable.insert(END, 'Obesity level III \t\t' + ">=40\n\n")

    btnBMI = Button(f2, text="Click to \nCheck Your \nBMI", padx=8, pady=8, bd=12, width=21,
                    font=('arial', 20, 'bold'), height=3, command=BMI_Cal)
    btnBMI.grid(row=2, column=0)

    btnC=Button(top3,text="Close Windows",bg="firebrick1",fg="Black",command=top3.destroy).place(x=520,y=620)
btn3=Button(root,text="Check BMI",bg="dark orange",fg="Black",command=BMICheck).place(x=100,y=750)

#Fourth Windows-------------------------------------------------------------------------------------------
def HelpWindows():
    top4=Toplevel()
    top4.geometry('500x500')
    top4.title("Help Desk Windows")

    SYQ= Label(top4, text="---Submit Your Query---", width=20,font=('arial',25,"bold"),bg="black",fg="White")
    SYQ.place(x=45,y=10)

    First_Name= Label(top4, text="First Name:-",font=('arial',15,'bold'),fg="lawn green")
    First_Name.place(x=10,y=100)
    First_Name_Box =Entry(top4,width=40,bg="aquamarine")
    First_Name_Box.place(x=200,y=100)

    Last_Name= Label(top4, text="Last Name:-", font=('arial', 15, 'bold'), fg="lawn green")
    Last_Name.place(x=10, y=130)
    Last_Name_Box = Entry(top4,width=40,bg="aquamarine")
    Last_Name_Box.place(x=200,y=130)

    Mobile_Number = Label(top4, text="Mobile Number:-", font=('arial', 15, 'bold'), fg="lawn green")
    Mobile_Number.place(x=10, y=160)
    Mobile_Number_Box = Entry(top4, width=40,bg="aquamarine")
    Mobile_Number_Box.place(x=200, y=160)

    Email_Id = Label(top4, text="Email Id:-", font=('arial', 15, 'bold'), fg="lawn green")
    Email_Id.place(x=10, y=190)
    Email_Id_Box = Entry(top4, width=40,bg="aquamarine")
    Email_Id_Box.place(x=200, y=190)

    AgeH = Label(top4, text="Age:-", font=('arial', 15, 'bold'), fg="lawn green")
    AgeH.place(x=10, y=220)
    v = IntVar()
    v.set(9)
    Age_Box=Spinbox(top4,from_=9,to=150, width=10, textvariable=v,bg="dark orange",bd=1)
    Age_Box.place(x=200, y=220)

    Query1 = Label(top4, text="Query:-", font=('arial', 15, 'bold'), fg="lawn green")
    Query1.place(x=10, y=250)
    Query_Box= Text(top4, height=9, width=30,bd=3,bg="misty rose")
    Query_Box.place(x=200, y=250)

    def SubmitPopPup():
        response = messagebox.askokcancel("Final Submissions!", "Confirm")
        Label(top4,text=response).pack()
    SubmitButton=Button(top4, text="Submit", font=('arial', 17, 'bold'), fg="maroon3",bg="snow3",command=SubmitPopPup)
    SubmitButton.place(x=200, y=420)

    btnC=Button(top4,text="Close Windows",bg="firebrick1",fg="Black",command=top4.destroy).place(x=400,y=470)
btn4=Button(root,text="Help Desk",bg="dark orange",fg="Black",command=HelpWindows).place(x=623,y=750)

#Fifth Windows-------------------------------------------------------------------------------------------
def AboutAC():
    top5=Toplevel()
    top5.geometry('350x500')
    top5.title("Aadhaar Card")

    ADCT= Label(top5, text="About Aadhaar Card", width=20, font=('arial', 18, "bold"), bg="Salmon", fg="White")
    ADCT.place(x=20, y=10)

    global my_imga
    my_imga = ImageTk.PhotoImage(Image.open("Aadhaarcard.png"))
    my_label = Label(top5,image=my_imga).place(x=20,y=50)

    ACDIWF=Text(top5,height=10,width=40, bg="light yellow")
    ACDIWF.insert(INSERT,"Aadhaar is a 12 digit individual identification number issued by the Unique Identification Authority of of India on behalf of the Government of India.The number serves as a proof of identity and address, anywhere in India.")
    ACDIWF.place(x=10,y=270)

    btnC=Button(top5,text="Close Windows",bg="firebrick1",fg="Black",command=top5.destroy).place(x=130,y=470)
btn5=Button(root,text="About Aadhaar Card",bg="dark orange",fg="Black",command=AboutAC).place(x=500,y=750)

#Sixth Windows-------------------------------------------------------------------------------------------
def PaymentSystem():
    top6=Toplevel()
    top6.geometry('500x400')
    top6.title("Payment System")

    PaymentH= Label(top6, text="Payment System", width=20, font=('arial', 23, "bold"), bg="green yellow", fg="White")
    PaymentH.place(x=55,y=10)

    Choose_Card = Label(top6, text="Choose Card:-", font=('arial', 15, 'bold'), fg="Blue")
    Choose_Card.place(x=10, y=100)
    var1=IntVar()
    Radiobutton(top6, text="Debit Card", variable=var1, value=1, bg="DarkGoldenrod1").place(x=180, y=100)
    Radiobutton(top6, text="Credit Card", variable=var1, value=2, bg="DarkGoldenrod1").place(x=270, y=100)
    Radiobutton(top6, text="Master Card", variable=var1, value=3, bg="DarkGoldenrod1").place(x=365, y=100)

    Card_Number = Label(top6, text="Card Number:-", font=('arial', 15, 'bold'), fg="Blue")
    Card_Number.place(x=10, y=135)
    RBFCN=StringVar()
    Card_Number_Box = Entry(top6, width=40, bg="Azure",textvariable=RBFCN)
    Card_Number_Box.place(x=200, y=140)

    Account_Number = Label(top6, text="Account Number:-", font=('arial', 15, 'bold'), fg="Blue")
    Account_Number.place(x=10, y=170)
    RBFAN=StringVar()
    Account_Number_Box = Entry(top6, width=40, bg="Azure",textvariable=RBFAN)
    Account_Number_Box.place(x=200, y=175)

    Account_Holder = Label(top6, text="Account Holder:-", font=('arial', 15, 'bold'), fg="Blue")
    Account_Holder.place(x=10, y=205)
    RBFAHN=StringVar()
    Account_Holder_Box = Entry(top6, width=40, bg="Azure",textvariable=RBFAHN)
    Account_Holder_Box.place(x=200, y=210)

    ExpireD= Label(top6, text="Expiration Date:-", font=('arial', 15, 'bold'), fg="Blue")
    ExpireD.place(x=10, y=240)
    RBFEN=StringVar()
    ExpireD_Box = Entry(top6, width=40, bg="Azure",textvariable=RBFEN)
    ExpireD_Box.place(x=200, y=245)

    CVC = Label(top6, text="CVC Code:-", font=('arial', 15, 'bold'), fg="Blue")
    CVC.place(x=10, y=275)
    RBFCVC=StringVar()
    CVC_Box = Entry(top6, width=40, bg="Azure",textvariable=RBFCVC)
    CVC_Box.place(x=200, y=280)
    def resetBF():
        RBFCN.set("")
        RBFAN.set("")
        RBFAHN.set("")
        RBFEN.set("")
        RBFCVC.set("")
        return

    SubmitPB = Button(top6, text="Submit", font=('arial', 15, 'bold'), fg="Red",bg="Bisque",command=resetBF)
    SubmitPB.place(x=200, y=330)

    btnC=Button(top6,text="Close Windows",bg="firebrick1",fg="Black",command=top6.destroy).place(x=400,y=370)
btn6=Button(root,text="Payment Method",bg="dark orange",fg="Black",command=PaymentSystem).place(x=172,y=750)

def savedata():
    conn=sqlite3.connect('PKPDatabase.db')
    c=conn.cursor()
    c.execute('INSERT INTO users(Firstname,Lastname,Fathername,Mothername,Dateofbirth,Villagename,Statename,Countryname) VALUES (?,?,?,?,?,?,?,?)',(FNR.get(),LNR.get(),FFNR.get(),MMNR.get(),DOBR.get(),VNBR.get(),SNBR.get(),CNBR.get()))
    conn.commit()
    print("Data Save Successfully")

SubmitButtonF1=Button(root,text="Submit",bg="yellow",fg="Black",bd=3,relief=RAISED,font=('arial',15,'bold'),command=savedata)
SubmitButtonF1.place(x=345,y=730)

root.mainloop()


import matplotlib.pyplot as plt
import numpy as np
import ast
import csv

x, x_1, x_2, x_3, x_4 = ([], [], [], [], [])
y, y_1, y_2, y_3, y_4 = ([], [], [], [], [])
A = np.arange(0, 20, 0.0001)
B = np.arange(0, 20, 0.001)
with open('data_mp_1024_1x.csv') as csvfile:
    plots = csv.reader(csvfile, delimiter=',')
    for i, row in enumerate(plots):
        x.append(i)
        y.append(ast.literal_eval(row[0]))

with open('data_mp_1024_2x.csv') as csvfile:
    plots = csv.reader(csvfile, delimiter=',')
    for i, row in enumerate(plots):
        x_2.append(i)
        y_2.append(ast.literal_eval(row[0]))

with open('data_mp_1024_3x.csv') as csvfile:
    plots = csv.reader(csvfile, delimiter=',')
    for i, row in enumerate(plots):
        x_3.append(i)
        y_3.append(ast.literal_eval(row[0]))

with open('data_mp_1024_4x.csv') as csvfile:
    plots = csv.reader(csvfile, delimiter=',')
    for i, row in enumerate(plots):
        x_4.append(i)
        y_4.append(ast.literal_eval(row[0]))

plt.step(x, y, where='pre', label='1024_bytes_1x')
plt.step(x_2, y_2, where='pre', label='1024_bytes_2x')
plt.step(x_3, y_3, where='pre', label='1024_bytes_3x')
plt.step(x_4, y_4, where='pre', label='1024_bytes_4x')
plt.plot(A, color='grey', alpha=0.3, label='True_10KHz')

# plt.xscale('log')
# plt.yscale('log')
plt.xlabel('nth sample')
plt.ylabel('sample time(sec)')
plt.grid(True)
# plt.xlim(2000, 20000)
plt.legend()
plt.show()


import click
import humanize

class AttributeFormatter:
    def format(self, formatter, value):
        return value

class BoldFormatter(AttributeFormatter):
    def format(self, formatter, value):
        if formatter.colorize:
            return click.style(value, bold=True)
        else:
            return value

class TagFormatter(AttributeFormatter):
    @staticmethod
    def get_tag_color(tag):
        tag_colors = {
            "bright_blue": [
                "spam",
                "suspicious",
                "unwanted",
                "apk",
                "pexe",
                "zip",
                "archive",
                "src:",
                "uploader:",
                "feed:",
            ],
            "bright_yellow": ["ripped:", "contains:", "matches:"],
            "bright_green": ["static:", "dynamic:"],
            "red": ["runnable:", "archive:", "dump:", "script:"],
        }
        for color, predecessors in tag_colors.items():
            for predecessor in predecessors:
                if tag.startswith(predecessor):
                    return color
        if ":" in tag:
            return "blue"
        return "bright_red"

    def format(self, formatter, value):
        if not value:
            return "<none>"
        if formatter.colorize:
            return " ".join(
                click.style(tag, fg=TagFormatter.get_tag_color(tag)) for tag in value
            )
        else:
            return " ".join(tag for tag in value)

class SizeFormatter(AttributeFormatter):
    def format(self, formatter, value):
        if formatter.humanize:
            return humanize.naturalsize(value)
        else:
            return value

class DateFormatter(AttributeFormatter):
    def format(self, formatter, value):
        if formatter.humanize:
            return humanize.naturaldate(value.replace(tzinfo=None))
        else:
            return value.isoformat()

class ObjectTypeFormatter(AttributeFormatter):
    @staticmethod
    def normalize_type(type):
        if type == "static_config":
            return "config"
        elif type == "text_blob":
            return "blob"
        return type

    def format(self, formatter, value):
        type_colors = {
            "file": "bright_red",
            "config": "bright_green",
            "blob": "bright_blue",
        }
        value = ObjectTypeFormatter.normalize_type(value)
        if formatter.colorize:
            return click.style(value, fg=type_colors.get(value))
        else:
            return value

class RelationTagFormatter(TagFormatter):
    def format(self, formatter, value):
        tags = set([tag for object in value for tag in object.tags])
        return super().format(formatter, list(tags))


from django.db import transaction
from drf_extra_fields.fields import Base64ImageField
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator

from recipes.models import (AmountOfIngredient, Favorite, Ingredient, Recipe,
                            ShoppingList, Tag)
from users.serializers import CurrentUserSerializer

class IngredientSerializer(serializers.ModelSerializer):
    """Сериализация ингредиентов."""

    class Meta:
        model = Ingredient
        fields = '__all__'

class AmountOfIngredientSerializer(serializers.ModelSerializer):
    """Сериализация количества ингредиентов."""
    id = serializers.PrimaryKeyRelatedField(
        source='ingredient',
        read_only=True
    )
    name = serializers.SlugRelatedField(
        slug_field='name',
        source='ingredient',
        read_only=True
    )
    measurement_unit = serializers.SlugRelatedField(
        slug_field='measurement_unit',
        source='ingredient',
        read_only=True
    )

    class Meta:
        model = AmountOfIngredient
        fields = '__all__'

class AddAmountOfIngredientSerializer(serializers.ModelSerializer):
    """Сериализация добавления количества ингредиентов."""
    id = serializers.PrimaryKeyRelatedField(
        source='ingredient',
        queryset=Ingredient.objects.all()
    )
    amount = serializers.IntegerField()

    class Meta:
        model = AmountOfIngredient
        fields = (
            'amount',
            'id',
        )

class TagSerializer(serializers.ModelSerializer):
    """Сериализация тэгов."""

    class Meta:
        model = Tag
        fields = (
            'id',
            'name',
            'color',
            'slug'
        )
        lookup_field = 'id'
        extra_kwargs = {'url': {'lookup_field': 'id'}}

class ShortRecipeSerializer(serializers.ModelSerializer):
    """Сериализация рецептов для списка покупок."""
    image = serializers.SerializerMethodField()

    class Meta:
        model = Recipe
        fields = (
            'id',
            'name',
            'image',
            'cooking_time'
        )

    def get_image(self, obj):
        request = self.context.get('request')
        image_url = obj.image.url
        return request.build_absolute_uri(image_url)

class RecipeSerializer(serializers.ModelSerializer):
    """Сериализация рецептов. Для списка рецептов."""
    author = CurrentUserSerializer(read_only=True)
    tags = TagSerializer(read_only=True, many=True)
    ingredients = serializers.SerializerMethodField()
    is_favorited = serializers.SerializerMethodField()
    is_in_shopping_cart = serializers.SerializerMethodField()

    class Meta:
        model = Recipe
        fields = (
            'id',
            'tags',
            'author',
            'ingredients',
            'is_favorited',
            'is_in_shopping_cart',
            'name',
            'image',
            'text',
            'cooking_time',
        )

    def get_ingredients(self, obj):
        recipe = obj
        queryset = recipe.recipes_ingredients_list.all()
        return AmountOfIngredientSerializer(queryset, many=True).data

    def get_is_favorited(self, obj):
        request = self.context.get('request')
        user = request.user
        return (
            not request.user.is_anonymous
            and Favorite.objects.filter(recipe=obj, user=user).exists()
            and request is not None
        )

    def get_is_in_shopping_cart(self, obj):
        request = self.context.get('request')
        user = request.user
        return (
            request is not None
            and not request.user.is_anonymous
            and ShoppingList.objects.filter(recipe=obj, user=user).exists()
        )

class RecipeAllFieldsSerializer(serializers.ModelSerializer):
    """Сериализация рецептов для методов POST, PUT и PATCH"""
    image = Base64ImageField(use_url=True, max_length=None)
    author = CurrentUserSerializer(read_only=True)
    ingredients = AddAmountOfIngredientSerializer(many=True)
    tags = serializers.PrimaryKeyRelatedField(
        queryset=Tag.objects.all(),
        many=True
    )
    cooking_time = serializers.IntegerField()

    class Meta:
        model = Recipe
        fields = (
            'id',
            'image',
            'tags',
            'author',
            'ingredients',
            'name',
            'text',
            'cooking_time',
        )

    def create_bulk(self, recipe, ingredients_data):
        AmountOfIngredient.objects.bulk_create([AmountOfIngredient(
            ingredient=ingredient['ingredient'],
            recipe=recipe,
            amount=ingredient['amount']
        ) for ingredient in ingredients_data])

    @transaction.atomic
    def create(self, validated_data):
        request = self.context.get('request')
        ingredients_data = validated_data.pop('ingredients')
        tags_data = validated_data.pop('tags')
        recipe = Recipe.objects.create(author=request.user, **validated_data)
        recipe.save()
        recipe.tags.set(tags_data)
        self.create_bulk(recipe, ingredients_data)
        return recipe

    @transaction.atomic
    def update(self, instance, validated_data):
        ingredients_data = validated_data.pop('ingredients')
        tags_data = validated_data.pop('tags')
        AmountOfIngredient.objects.filter(recipe=instance).delete()
        self.create_bulk(instance, ingredients_data)
        instance.name = validated_data.pop('name')
        instance.text = validated_data.pop('text')
        instance.cooking_time = validated_data.pop('cooking_time')
        if validated_data.get('image') is not None:
            instance.image = validated_data.pop('image')
        instance.save()
        instance.tags.set(tags_data)
        return instance

    def to_representation(self, instance):
        data = RecipeSerializer(
            instance,
            context={'request': self.context.get('request')}
        ).data
        return data

class FavoriteSerializer(serializers.ModelSerializer):
    """Сериализация избранного."""

    class Meta:
        model = Favorite
        fields = ('user', 'recipe')
        validators = [
            UniqueTogetherValidator(
                queryset=Favorite.objects.all(),
                fields=('user', 'recipe'),
                message='Рецепт уже в избранном'
            )
        ]

    def to_representation(self, instance):
        request = self.context.get('request')
        return ShortRecipeSerializer(
            instance.recipe,
            context={'request': request}
        ).data

class ShoppingListSerializer(FavoriteSerializer):
    """Сериализация списка покупок."""

    class Meta(FavoriteSerializer.Meta):
        model = ShoppingList
        fields = ('user', 'recipe')
        validators = [
            UniqueTogetherValidator(
                queryset=ShoppingList.objects.all(),
                fields=('user', 'recipe'),
                message='Рецепт уже в списке покупок'
            )
        ]

    def to_representation(self, instance):
        request = self.context.get('request')
        return ShortRecipeSerializer(
            instance.recipe,
            context={'request': request}
        ).data