#!/usr/bin/python
# -*- coding: utf-8 -*-
from xml.etree.cElementTree import Element, ElementTree, SubElement
import DBA
import cairo
import time
import re
from transformation import *
[docs]class Extract:
"""
Purpose to extract campaign data measure in XML or PNG file.
:arguments:
- id_campaign (type integer)
Represents the numbre of campaign which we want extract data.
- fichier (type string)
Chose the name of extraction
**exemple**
>>> id_campaign = 2
>>> fichier = 'essai_extract'
ex = Extract(id_campaign,fichier)
ex.toXML()
ex.toPNG()
"""
def __init__(self,id_area_arg,id_place_arg,id_ap_arg,id_campaign_arg,fichier_arg,main=None):
"""
Recovery of generic parameters such as:
* the area number
* the number or numbers of the square
* the number or numbers of ap
* the number or numbers of the campaign
* name of the extract file
"""
self.main_app=main
self.id_area = id_area_arg
self.id_place = id_place_arg
self.id_ap = id_ap_arg
self.id_campaign = id_campaign_arg
self.fichier = fichier_arg
self.db = DBA.DBConnect(main=self.main_app)
[docs] def toXML(self):
"""
The function 'toXML' permit to extract information from an XML file in BDD
The XML file follows the new version of the database
:return:
file .xml created on the current directory
"""
#Date recovery
date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
#Tag GWA
gwa = Element("gwa", {'date':date, 'xmlns:xsi':"http://www.w3.org/2001/XMLSchema-instance", 'xsi:schemaLocation':"http://gwa.sourceforge.net/extract/gwaExtract.xsd"})
#Queries SQL area
area_list = self.db.select('area',\
['id_area','name','width','length', 'height', 'x_coordinate_area', 'y_coordinate_area', 'z_coordinate_area', 'description', 'origin_info'],\
{'id_area':self.id_area})
#loop on the area
for id_area_sql, name_area_sql, width_area_sql, length_area_sql, height_area_sql, x_coordinate_area_sql, y_coordinate_area_sql, z_coordinate_area_sql, description_area_sql, origin_info_area_sql in area_list:
#Balise AREA
area = Element("area")
#AREA arguments
nameArea = Element("nameArea")
nameArea.text = name_area_sql.decode("utf-8")
area.append(nameArea)
widthArea = Element("widthArea")
widthArea.text = str(width_area_sql).decode("utf-8")
area.append(widthArea)
lengthArea = Element("lengthArea")
lengthArea.text = str(length_area_sql).decode("utf-8")
area.append(lengthArea)
heightArea = Element("heightArea")
heightArea.text = str(height_area_sql).decode("utf-8")
area.append(heightArea)
x_coordinate_area_origin = Element("x_coordinate_area_origin")
x_coordinate_area_origin.text = str(x_coordinate_area_sql).decode("utf-8")
area.append(x_coordinate_area_origin)
y_coordinate_area_origin = Element("y_coordinate_area_origin")
y_coordinate_area_origin.text = str(y_coordinate_area_sql).decode("utf-8")
area.append(y_coordinate_area_origin)
z_coordinate_area_origin = Element("z_coordinate_area_origin")
z_coordinate_area_origin.text = str(z_coordinate_area_sql).decode("utf-8")
area.append(z_coordinate_area_origin)
descriptionArea = Element("descriptionArea")
descriptionArea.text = u""+description_area_sql.decode("utf-8")
area.append(descriptionArea)
origin_infoArea = Element("origin_infoArea")
origin_infoArea.text = origin_info_area_sql.decode("utf-8")
area.append(origin_infoArea)
#loop on the places
self.__place(area, id_area_sql)
gwa.append(area)
#Call the function prettyprint
self.__prettyprint(gwa)
#Creation of the tree
xmltree = ElementTree(gwa)
#Write file
xmltree.write(self.fichier, encoding="utf-8")
def __place(self, area, id_area):
"""
The function '__place()' permit writting XML file for the part of place
:argument:
area (type Element)
Top tag
id_area (type Int)
area number
"""
#Loop on the places selected by the user
for id_place_user in self.id_place:
#Queries SQL place
place_list = self.db.select('place',\
['id_place', 'name', 'width', 'length', 'height', 'x_coordinate_area', 'y_coordinate_area', 'z_coordinate_area', 'angle', 'description', 'origin_info'],\
{'id_area':id_area, 'id_place':id_place_user})
#Loop on the places
for id_place_ap, name_place_ap, width_place_ap, length_place_ap, height_place_ap, x_coordinate_area_place_ap, y_coordinate_area_place_ap,\
z_coordinate_area_place_ap, angle_place_ap, description_place_ap, origin_info_place_ap in place_list:
#Tag PLACE
place = Element("place")
id_place = id_place_ap
#PLACE arguments
namePlace = Element("namePlace")
namePlace.text = name_place_ap.decode("utf-8")
place.append(namePlace)
widthPlace = Element("widthPlace")
widthPlace.text = str(width_place_ap).decode("utf-8")
place.append(widthPlace)
lengthPlace = Element("lengthPlace")
lengthPlace.text = str(length_place_ap).decode("utf-8")
place.append(lengthPlace)
heightPlace = Element("heightPlace")
heightPlace.text = str(height_place_ap).decode("utf-8")
place.append(heightPlace)
x_coordinate_area = Element("x_coordinate_area")
x_coordinate_area.text = str(x_coordinate_area_place_ap).decode("utf-8")
place.append(x_coordinate_area)
y_coordinate_area = Element("y_coordinate_area")
y_coordinate_area.text = str(y_coordinate_area_place_ap).decode("utf-8")
place.append(y_coordinate_area)
z_coordinate_area = Element("z_coordinate_area")
z_coordinate_area.text = str(z_coordinate_area_place_ap).decode("utf-8")
place.append(z_coordinate_area)
angle = Element("angle")
angle.text = str(angle_place_ap).decode("utf-8")
place.append(angle)
#Creation of the matrix transformation
self.trans_g = Transformation(x_coordinate_area_place_ap, y_coordinate_area_place_ap, z_coordinate_area_place_ap, angle_place_ap)
descriptionPlace = Element("descriptionPlace")
descriptionPlace.text = description_place_ap.decode("utf-8")
place.append(descriptionPlace)
origin_infoPlace = Element("origin_infoPlace")
origin_infoPlace.text = origin_info_place_ap.decode("utf-8")
place.append(origin_infoPlace)
#Loop on the campaign
self.__campaign(place, id_place)
area.append(place)
def __campaign(self, place, id_place):
"""
The function '__campaign()' permit writting XML file for the part of campaign
:argument:
place (type Element)
Top tag
id_place (type Int)
Place number
"""
#Loop on campaigns selected by the user
for id_campaign_user in self.id_campaign:
#Queries SQL campaign
campaign_list = self.db.select('campaign',\
['id_campaign','name','x_step','y_step','z_step','date','eperf_parameters','rts_cts','fragment','tx_power'],\
{'id_place':id_place,'id_campaign':id_campaign_user})
#Loop on the campaign
for id_campaign_sql, name_campaign_sql, x_step_campaign_sql, y_step_campaign_sql, z_step_campaign_sql, date_campaign_sql,\
eperf_parameters_campaign_sql, rts_cts_campaign_sql, fragment_campaign_sql, tx_power_campaign_sql in campaign_list:
#Tag CAMPAIGN
campaign = Element("campaign")
id_campaign = id_campaign_sql
#CAMPAIGN Arguments
nameCampaign = Element("nameCampaign")
nameCampaign.text = name_campaign_sql.decode("utf-8")
campaign.append(nameCampaign)
x_step = Element("x_step")
x_step.text = str(x_step_campaign_sql).decode("utf-8")
campaign.append(x_step)
y_step = Element("y_step")
y_step.text = str(y_step_campaign_sql).decode("utf-8")
campaign.append(y_step)
z_step = Element("z_step")
z_step.text = str(z_step_campaign_sql).decode("utf-8")
campaign.append(z_step)
date = Element("date")
date.text = str(date_campaign_sql).decode("utf-8")
campaign.append(date)
eperf_parameters = Element("eperf_parameters")
if eperf_parameters_campaign_sql:
address_server, port_server, measure_time_eperf, interval_time_eperf, name_protocol_eperf, packet_size_eperf, rate_eperf, connectionTCP, directionUpOrDown = re.split(';', eperf_parameters_campaign_sql)
#EPERF_PARAMETERS arguments
add_server = Element("server_address")
add_server.text = str(address_server).decode("utf-8")
eperf_parameters.append(add_server)
p_server = Element("server_port")
p_server.text = port_server.decode("utf-8")
eperf_parameters.append(p_server)
measure_time = Element("measure_time")
measure_time.text = measure_time_eperf.decode("utf-8")
eperf_parameters.append(measure_time)
interval_time = Element("time_interval")
interval_time.text = str(interval_time_eperf).decode("utf-8")
eperf_parameters.append(interval_time)
protocol = Element("protocol")
#PROTOCOL arguments
name = Element("name")
name.text = name_protocol_eperf.decode("utf-8")
protocol.append(name)
direction = Element("direction")
direction.text = str(directionUpOrDown).decode("utf-8")
protocol.append(direction)
packet_size = Element("packet_size")
packet_size.text = str(packet_size_eperf).decode("utf-8")
protocol.append(packet_size)
rate = Element("rate_UDP")
rate.text = str(rate_eperf).decode("utf-8")
protocol.append(rate)
connection = Element("connection_TCP")
connection.text = str(connectionTCP).decode("utf-8")
protocol.append(connection)
eperf_parameters.append(protocol)
campaign.append(eperf_parameters)
#Loop on the AP
self.__ap_list(campaign, id_campaign)
#Loop on the measures
self.__measure(campaign, id_campaign)
place.append(campaign)
def __ap_list(self, campaign, id_campaign):
"""
The function '__ap_list()' permit writting XML file for the part of AP list
:argument
campaign (type Element)
Top tag
id_place (type Int)
place number
id_campaign (type Int)
campaign number
"""
aps = Element("aps")
#Loop through the user selected APs
for id_ap_user in self.id_ap:
#Queries SQL AP configuration
ap_conf = self.db.select('ap_configuration',\
[ 'channel', 'encryption', 'standard'],\
{'id_campaign':id_campaign,'id_ap':id_ap_user});
#Loop on the APs of the campaign
for channel_ap_conf_sql, encryption_ap_conf_sql, standard_ap_conf_sql in ap_conf:
#Queries SQL AP
req_sql = self.db.select('ap',\
['essid', 'mac_address','x_coordinate_place', 'y_coordinate_place', 'z_coordinate_place', 'description'], {'id_ap':id_ap_user})
essid_ap_sql,mac_address_ap_conf_sql, x_coordinate_place_ap_sql, y_coordinate_place_ap_sql, z_coordinate_place_ap_sql, description_ap_sql = req_sql[0]
#Tag AP
ap = Element("ap")
#AP arguments
macAddress_Ap = Element("macAddress_Ap")
macAddress_Ap.text = mac_address_ap_conf_sql.decode("utf-8")
ap.append(macAddress_Ap)
essid_Ap = Element("essid_Ap")
essid_Ap.text = essid_ap_sql.decode("utf-8")
ap.append(essid_Ap)
x_coordinate_place_Ap = Element("x_coordinate_place_Ap")
x_coordinate_place_Ap.text = str(x_coordinate_place_ap_sql).decode("utf-8")
ap.append(x_coordinate_place_Ap)
y_coordinate_place_Ap = Element("y_coordinate_place_Ap")
y_coordinate_place_Ap.text = str(y_coordinate_place_ap_sql).decode("utf-8")
ap.append(y_coordinate_place_Ap)
z_coordinate_place_Ap = Element("z_coordinate_place_Ap")
z_coordinate_place_Ap.text = str(z_coordinate_place_ap_sql).decode("utf-8")
ap.append(z_coordinate_place_Ap)
#Recovery of the global coordinates
x_coordinate_area_place_trans, y_coordinate_area_place_trans, z_coordinate_area_place_trans = self.trans_g.localToGlobal(x_coordinate_place_ap_sql, y_coordinate_place_ap_sql, z_coordinate_place_ap_sql)
x_coordinate_area_Ap = Element("x_coordinate_area_Ap")
x_coordinate_area_Ap.text = str(int(x_coordinate_area_place_trans)).decode("utf-8")
ap.append(x_coordinate_area_Ap)
y_coordinate_area_Ap = Element("y_coordinate_area_Ap")
y_coordinate_area_Ap.text = str(int(y_coordinate_area_place_trans)).decode("utf-8")
ap.append(y_coordinate_area_Ap)
z_coordinate_area_Ap = Element("z_coordinate_area_Ap")
z_coordinate_area_Ap.text = str(int(z_coordinate_area_place_trans)).decode("utf-8")
ap.append(z_coordinate_area_Ap)
channel_Ap = Element("channel_Ap")
channel_Ap.text = str(channel_ap_conf_sql).decode("utf-8")
ap.append(channel_Ap)
encryption_Ap = Element("encryption_Ap")
encryption_Ap.text = str(encryption_ap_conf_sql).decode("utf-8")
ap.append(encryption_Ap)
description_Ap = Element("description_Ap")
description_Ap.text = description_ap_sql.decode("utf-8")
ap.append(description_Ap)
#Add AP in APS
aps.append(ap)
campaign.append(aps)
def __measure(self, campaign, id_campaign):
"""
The function '__measure()' permit writting XML file for the part of measures
:argument:
campaign (type Element)
Top tag
id_campaign (type Int)
Campaign number
"""
measures = Element("measures")
#Loop through the user selected APs
for id_ap_user in self.id_ap:
#Queries SQL measures
measure_list = self.db.select('measure',\
['id_measure','id_ap','x_coordinate_place','y_coordinate_place','z_coordinate_place','signal_level','noise_level','bitrate_level2','rate_level4','timestamp'],\
{'id_campaign':id_campaign,'id_ap':id_ap_user})
#loop on the measure
for id_measure_measure_sql, id_ap_measure_sql, x_coordinate_place_measure_sql, y_coordinate_place_measure_sql, z_coordinate_place_measure_sql, signal_level_measure_sql,\
noise_level_measure_sql, bitrate_level2_measure_sql, rate_level4_measure_sql, timestamp_measure_sql in measure_list:
#tag MEASURE
measure = Element("measure")
#MEASURE Arguments
timestamp = Element("timestamp")
timestamp.text = timestamp_measure_sql.decode("utf-8")
measure.append(timestamp)
macAddress_measure = Element("macAddress_measure")
macAddress_measure.text = str(self.db.select('ap','mac_address',{'id_ap':id_ap_measure_sql})[0][0]).decode("utf-8")
#macAddress_measure.text = mac_address_measure_sql.decode("utf-8").decode("utf-8")
measure.append(macAddress_measure)
x_coordinate_place = Element("x_coordinate_place")
x_coordinate_place.text = str(x_coordinate_place_measure_sql).decode("utf-8")
measure.append(x_coordinate_place)
y_coordinate_place = Element("y_coordinate_place")
y_coordinate_place.text = str(y_coordinate_place_measure_sql).decode("utf-8")
measure.append(y_coordinate_place)
z_coordinate_place = Element("z_coordinate_place")
z_coordinate_place.text = str(z_coordinate_place_measure_sql).decode("utf-8")
measure.append(z_coordinate_place)
#Recovery of the global coordinates
x_coordinate_area_place_trans, y_coordinate_area_place_trans, z_coordinate_area_place_trans = self.trans_g.localToGlobal(x_coordinate_place_measure_sql, y_coordinate_place_measure_sql, z_coordinate_place_measure_sql)
x_coordinate_global = Element("x_coordinate_global")
x_coordinate_global.text = str(int(x_coordinate_area_place_trans)).decode("utf-8")
measure.append(x_coordinate_global)
y_coordinate_global = Element("y_coordinate_global")
y_coordinate_global.text = str(int(y_coordinate_area_place_trans)).decode("utf-8")
measure.append(y_coordinate_global)
z_coordinate_global = Element("z_coordinate_global")
z_coordinate_global.text = str(int(z_coordinate_area_place_trans)).decode("utf-8")
measure.append(z_coordinate_global)
noise_level = Element("noise_level")
noise_level.text = str(noise_level_measure_sql).decode("utf-8")
measure.append(noise_level)
signal_level_measure = Element("signal_level_measure")
signal_level_measure.text = str(signal_level_measure_sql).decode("utf-8")
measure.append(signal_level_measure)
bit_rate_level = Element("bit_rate_level")
bit_rate_level.text = str(bitrate_level2_measure_sql).decode("utf-8")
measure.append(bit_rate_level)
rate_level = Element("rate_level")
rate_level.text = str(rate_level4_measure_sql).decode("utf-8")
measure.append(rate_level)
environment = Element("environment")
#Loop on the disturbing detected AP
self.__disturbing_ap(environment,id_measure_measure_sql)
measure.append(environment)
#Add MEASURE in MEASURES
measures.append(measure)
campaign.append(measures)
def __disturbing_ap(self, environment, id_measure):
"""
The function '__write_disturbing_ap()' permit writting XML file for the part of disturbing_ap
:argument:
environment (type Element)
Top tag
id_measure (type Int)
Measure number
"""
#Creation of the SQL queries
result_disturbing_ap = self.db.select('disturbing_ap',\
['essid', 'mac_address', 'channel', 'encryption', 'protocol', 'signal_level'],\
{'id_measure':id_measure})
#Loop on the disturbing detected AP
for essid_sql, mac_address_sql, channel_sql, encryption_sql, protocol_sql, signal_level_sql in result_disturbing_ap :
#TagDISTURBING_AP
disturbing_ap = Element("disturbing_ap")
#DISTURBING_AP Arguments
macAddress = Element("macAddress")
macAddress.text = mac_address_sql.decode("utf-8")
disturbing_ap.append(macAddress)
essid = Element("essid")
essid.text = essid_sql.decode("utf-8")
disturbing_ap.append(essid)
channel = Element("channel")
channel.text = str(channel_sql).decode("utf-8")
disturbing_ap.append(channel)
encryption = Element("encryption")
encryption.text = encryption_sql.decode("utf-8")
disturbing_ap.append(encryption)
signal_level = Element("signal_level")
signal_level.text = str(signal_level_sql).decode("utf-8")
disturbing_ap.append(signal_level)
#Add of DISTURBING_AP in ENVIRONMENT
environment.append(disturbing_ap)
def __prettyprint(self, root, level=0):
"""
The function '__prettyprint' used to indent the output in a format xml
:argument:
element (type Element)
choice of root indent
This function must be called before writing to a file
"""
i = "\n" + level*" "
if len(root):
if not root.text or not root.text.strip():
root.text = i + " "
if not root.tail or not root.tail.strip():
root.tail = i
for child in root:
self.__prettyprint(child, level+1)
if not child.tail or not child.tail.strip():
child.tail = i
if not root.tail or not root.tail.strip():
root.tail = i
else:
if level and (not root.tail or not root.tail.strip()):
root.tail = i
def __format_sql_result(self, result_sql):
"""
The function '__format_sql_result' used to format string as the result of an SQL query.
By default, the result of an SQL query is a list of list
This function is required for the creation of Element or SubElement
"""
result_sql = result_sql[0]
liste_temp = []
for row in result_sql:
liste_temp.append(str(row))
return liste_temp
[docs] def toPNG(self,resolution=100, legende=True, amplitude=''):
"""
The function 'toXML' to extract information from the BDD in a PNG file
:arguments optionels:
resolution (type integer)
You can choose the resolution of the drawing. By default it is 50
legende (type Boolean)
Adds legend drawing, otherwise returns the surface
amplitude (type integer)
Allows you to choose which power ranges are defined colors
:return:
. png file created on the current directory
"""
#Recovery information in the DB to create the image file
lieux_taille = self.db.select(['campaign','place','area'],\
['place.length','place.width', 'area.name', 'place.name', 'campaign.name', 'campaign.date'],\
{'campaign.id_campaign':self.id_campaigne,'place.id_place':'campaign.id_place', 'place.id_area':'area.id_area'})
width, height, batiment, lieux, campagne, date = lieux_taille[0]
width_pix, height_pix = [val*resolution for val in [width, height]]
#Creation of file
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width_pix, height_pix)
self.context = cairo.Context(self.surface)
self.context.scale(self.surface.get_width(),self.surface.get_height())
self.context.set_source_rgb(1, 1, 1)
self.context.paint()
#Recovery of steps to calculate the number of points to create the points
step_x, step_y = self.db.select('campaign',['x_step','y_step'], {'id_campaign':self.id_campagne})[0]
if width > height:
rayon = (float(resolution) / height_pix)*1.5
else:
rayon = (float(resolution) / width_pix)*1.5
if not amplitude:
amplitude = FindAmplitude(self.id_campagne).get()
#Recovery of all steps of the campaign
mesures = self.db.select('measure',['x_coordinate_place','y_coordinate_place', 'signal_level'],{'id_campaign':self.id_campagne})
#Creation points
for mesure in mesures:
#define color
red, green, blue = FloatRgbMulti(mesure[2],amplitude[0],amplitude[1]).get()
self.context.save()
#We define two circles x, y, with different radius and a color effect
y = (height-(height-mesure[1])) / float(height)
x=mesure[0]
self.context.scale(height/float(width),1)
radial = cairo.RadialGradient(x/float(height), y, rayon*0.1, x/float(height), y, rayon)
radial.add_color_stop_rgba(0, 0, 0, 0, 1)
radial.add_color_stop_rgba(0.7, 0, 0, 0, 0)
self.context.set_source_rgb(red, green, blue)
self.context.mask(radial)
self.context.restore()
#If we add a caption to the drawing
if legende:
if width_pix >= height_pix: #It gets the largest side to:
leg_x, leg_y = width_pix, 0 #-position the legend so large drawing, we put the caption on the right, if not lower.
maximum = width_pix #-define the size of the legend (20% of the largest side
width_pix *= 1.2
else:
leg_x, leg_y = 0, height_pix
maximum = height_pix
height_pix *= 1.2
#Creation of the legend with four information placed in the list (argument 1),
#Recuperation des steps afin de calculer le nombre de point à créer les points
#the minimum and maximum values used for coloring (argument 2 & 3), and the size of the largest side (argument 4)
surface_legende = Legende( [('Batiment',batiment),('Lieux',lieux),('Campagne',campagne),('Date',date)],\
amplitude[0], amplitude[1], maximum).get()
#We recreate a large surface + to paste the drawing + legend on a white background
surface_with_legende = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width_pix), int(height_pix))
context = cairo.Context(surface_with_legende)
context.set_source_rgb(1, 1, 1)
context.paint()
#Collage drawing
context.set_source_surface(self.surface, 0, 0)
context.paint()
#Collage of the legend
context.set_source_surface(surface_legende, leg_x, leg_y)
context.paint()
#Write File
surface_with_legende.write_to_png(self.fichier+'.png')
else:#Otherwise it returns the surface in order to use the design
return self.surface
[docs]class FloatRgbMulti:
"""
The class 'FloatRgbMulti' sets the range of colors that will be applied on the graph.
It provided a color depending on mag between cmin et cmax.
:arguments:
mag (type integer)
Choice of the magnitude
cmin (type integer)
Choosing the minimum value that will be represented by a color
cmax (type integer)
Choice of max will be represented by a color
:couleurs:
Warm color for high values(rouge)
Cool color for low values(bleu ciel)
:return:
Tuple as (reg, green, blue)
"""
def __init__(self, mag, cmin, cmax):
#normalization with respect to mag cmin and cmax
try:
x = float(mag-cmin)/float(cmax-cmin)
#case of division by 0
except:
if mag == cmin:
x = 0.5
#definition d' 1/3
tiers = 1/float(3)
#Algo:
#To vary the colors we can divide the process into three parts (or third)
#A variation of the green, then red and finally blue each time between 1.0 and 0.0
#We look for what is our third value
#then renormalize this value to know what is the corresponding intensity
if x >= 1.5*tiers:
self.red = 1
self.green = 1-(x-(2*tiers))/tiers
self.blue = 0
elif x <= 0.8*tiers:
self.red = 0
self.green = 1
self.blue = 1-(x / tiers)
else:
self.red = (x-tiers)/(2*tiers)
self.green = 1
self.blue = 0
[docs] def get(self):
"""
This function retrieves the color code
"""
return (self.red, self.green, self.blue)
[docs]class FindAmplitude:
"""
To find the amplitude was applied to a extract.PNG () to one or more campaign!
"""
def __init__(self, id_campagnes):
liste_id_campagne=[]
all_mesure=[]
db = DBA.DBConnect()
if type(id_campagnes) == int:
liste_id_campagne.append(id_campagnes)
else:
liste_id_campagne = id_campagnes
for id_campagne in liste_id_campagne:
mesures = db.select('measure',['signal_level'],{'id_campaign':id_campagne},('signal_level','DESC'))
for mesure in mesures:
all_mesure.append(mesure[0])
max_power = -100
min_power = 0
power_liste_clean=[]
#it gets the max and min values measured outside the -100 to 0 to find the amplitude measures
for power in all_mesure:
if power < 0 and power > max_power:
max_power = power
elif power > -100 and power < min_power:
min_power = power
if power < 0 and power > -100:
power_liste_clean.append(power)
amplitude_temp=max_power-min_power
#it gets the max and min values measured outside the -100 to 0 to find the amplitude measures
somme = 0
for power in power_liste_clean:
somme += power
moyenne= somme / len(power_liste_clean)
#It was decided that the range of values for the drawing is equal to the average + or - 80% of the amplitude
self.amplitude = (moyenne-amplitude_temp*0.3, moyenne+amplitude_temp*0.5)
def get(self):
return self.amplitude
[docs]class DessinBatiment:
"""
Can be extracted into a PNG, the results of a set of campaign
:arguments:
- liste_id_campagne (type list)
List with the numbers of campaign we want to show
- fichier (type string)
Selecting the name of the file extraction, is extansion. Png is added automatically
- resolution (type integer)
Optional parameter to adjust the resolution in pixels per meter. (default = 100)
**exemple**
>>> liste_id_campagne = [1,2,3,4]
>>> file = 'essai_extract'
dessinBatiment(liste_id_campagne,fichier, 100)
"""
def __init__(self, liste_id_campagne, fichier='DessinBatiment', resolution=100):
width = height = 0
coor_list = []
#Recovery of the name of the building for the legend
batiment = DBA.DBConnect().select(['area', 'place', 'campaign'],\
['area.name'],\
{'campaign.id_campaign' : liste_id_campagne[0],\
'campaign.id_place':'place.id_place',\
'place.id_area':'area.id_area'})[0][0]
#To set the final file size is sought for each of the campaigns
#max-value of the coordinate of the part + length on two axes
#backup-coordinates of the rooms in a list to see where glue surfaces
for id_campagne in liste_id_campagne:
resultat = DBA.DBConnect().select(['campaign','place'],\
['campaign.id_place','x_coordinate_area','y_coordinate_area','widht','length'],\
{'campaign.id_place':'place.id_place', 'campaign.id_campaign':id_campagne})[0]
if width < resultat[1] + resultat[4]:
width = resultat[1] + resultat[4]
if height < resultat[2] + resultat[3]:
height = resultat[2] + resultat[3]
coor_list.append((resultat[1]*resolution,resultat[2]*resolution))
width_pix = width*resolution
height_pix = height*resolution
#Same algorithm as for adding a legend in extract.toPNG ()
if width_pix >= height_pix:
leg_x, leg_y = width_pix, 0
maximum = width_pix
width_pix *= 1.2
else:
leg_x, leg_y = 0, height_pix
maximum = height_pix
height_pix *= 1.2
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width_pix), int(height_pix))
context = cairo.Context(surface)
context.set_source_rgb(1, 1, 1)
context.paint()
#Search the magnitude of pattern based on all campaigns
amplitude = FindAmplitude(liste_id_campagne).get()
#Generate the surface for each of the campaigns and pasting on the final design
compteur = 0
for id_campagne in liste_id_campagne:
surface_temp = Extract(id_campagne, "useless").toPNG(resolution, False, amplitude)
context.set_source_surface(surface_temp, coor_list[compteur][0], coor_list[compteur][1])
context.paint()
compteur += 1
#Generate the surface legend and paste
surface_legende = Legende( [('Batiment',batiment)], amplitude[0], amplitude[1], maximum).get()
context.set_source_surface(surface_legende, leg_x, leg_y)
context.paint()
#Write files
surface.write_to_png(fichier+'.png')
[docs]class Legende:
"""
Generates the surface corresponding to the caption of a drawing
:arguments:
- informations (type list)
List of tuple, where each tuple contains the name of information and information
- power_min (type int)
Min power used for the color of the drawing
- power_max (type int)
Max power used for the color of the drawing
- size
the pixel size of the largest side of the drawing
**exemple**
>>> amplitude = FindAmplitude(numerodecampagne).get()
>>> leg = Legende([('Batiment','Maison'),('Pièce','Chambre'),('Campagne','Première'),('Date','17/11/85')],amplitudetest[0], amplitudetest[1], 2100).get()
extract(numerodecampagne,'testaveclegende').toPNG(100)
"""
def __init__(self, informations, power_min, power_max, size):
#The base area of a size
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(size*0.2), int(size*0.2))
context = cairo.Context(self.surface)
context.set_source_rgb(1, 1, 1)
context.paint()
self.reference = size*0.2 #variable used to rescale the function dynamically place the elements of the legend
#All values below are referenced on a matrix 1 / 1 (a square of side 1)
#rescale the function multiplies the reference values to adapt the result
#Creation of the rectangle with the gradient
context.rectangle(self.rescale(0.85),self.rescale(0.15),self.rescale(0.125),self.rescale(0.8)) #x, y, largeur, hauteur
ligne = cairo.LinearGradient(self.rescale(0.5), self.rescale(0.15), self.rescale(0.5), self.rescale(0.9)) #pour la colorisation
#creation of 10 points in the gradient colors
for i in range(10,0,-1):
r, g, b = FloatRgbMulti(i, 1, 10).get()
ligne.add_color_stop_rgba(1-i*0.1, r, g, b, 1)
context.set_source(ligne)
context.fill()
#Creating the Legend title
context.set_source_rgb(0,0,0)
context.select_font_face("Georgia", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
context.set_font_size(self.rescale(0.10))
context.move_to(self.rescale(0.27), self.rescale(0.1) )
context.show_text("Légende")
#Creation of values at the ends of the rectangle
context.set_font_size(self.rescale(0.05))
context.select_font_face("Georgia", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
context.move_to(self.rescale(0.65),self.rescale(0.2))
context.show_text(str(int(power_max))+'dB')
context.move_to(self.rescale(0.65),self.rescale(0.925))
context.show_text(str(int(power_min))+'dB')
#Creating titles and information
level = self.rescale(0.2)
for info in informations:
context.move_to(self.rescale(0.05),level)
context.select_font_face("Georgia", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
context.show_text("%s :" % info[0])
context.move_to(self.rescale(0.075), level+self.rescale(0.05))
context.select_font_face("Georgia", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
context.show_text(info[1])
level += self.rescale(0.2)
[docs] def rescale(self, x):
"""
Customize the text and the forms of the legend according to the size of the final image
"""
return x*self.reference
if __name__=="__main__":
#amplitudetest = FindAmplitude(151).get()
#leg = Legende( [('Batiment','Maison'), ('Pièce','Chambre'), ('Campagne','Première'), ('Date','17/11/85')], amplitudetest[0], amplitudetest[1], 2100).get()
#Extract(151,'testaveclegende').toPNG(100, leg)
#DessinBatiment([151,152])
#Extract(151,'Premiere').toXML()
Extract(1,[1],[1,2,3],1,'Premiere').toXML()