Writing to databases on Python - python

I have been trying to write to a database and am having trouble setting data using two different classes in the one function.
Firstly, all values are being passed through a GUI and in this case, only the following entries were passed: 'Categories' = C, 'Usage' = Charter, 'DispTHR' = 5000.
Here you can see that I have two classes I am wanting to access (airport and runway) where the function set_opsdatabase_details() will go to the appropriate class and write to our database. This is all well and good when the airport and runway are separate from each other; however, when integrating them in the same function I can't seem to get the corresponding airportvalueDict = {} and runwayvalueDict = {] to display the values I want. Could someone help me understand how to write the correct entry box values into the corresponding valueDict dictionaries?
Thank you in advance! (a screenshot of the output from the print statements is attached)
Function in python
Output of function with the print statements
Example of code in text format:
#edit function for first part of operational window
def edit_details1(self):
airport = self.manager.get_chosen_airport()
runway = airport.get_chosen_runway()
airportlabels = ['Category', 'Usage', 'Curfew',
'Surveyor', 'LatestSurvey',
'FuelAvail', 'FuelPrice', 'TankerPort', 'RFF']
runwaylabels = ['DispTHR', 'VASI', 'TCH']
airportvalueDict = {}
runwayvalueDict = {}
print(self.entryDict['Category']["state"])
if self.entryDict['Category']["state"] == 'disabled':
for entry in self.entryDict.values():
entry.config(state=tk.NORMAL)
self.editButton.config(text="Confirm")
elif self.entryDict['Category']['state'] == 'normal':
airport = self.manager.get_chosen_airport()
runway = airport.get_chosen_runway()
values = [x.get() for x in self.varDict.values()]
for label, value in zip(airportlabels, values):
airportvalueDict[label] = value
airport.set_opsdatabase_details(airportvalueDict)
print(f'airport: {airportvalueDict}')
for label, value in zip(runwaylabels, values):
runwayvalueDict[label] = value
runway.set_opsdatabase_details(runwayvalueDict)
print(f'runway: {runwayvalueDict}')
for entry in self.entryDict.values():
entry.config(state=tk.DISABLED)
self.editButton.config(text="Edit...")

Related

Python: Create objects of a class dynamically using a string and then refer to them using that same string

I have a python script that reads a configuration file CSV, e.g.
#PV_name, type
motor_temp_1, 15m
tank_pressure_1, 15m
pump_flow_2, 60m
...
variable_X, 24h
The data is then saved on a dictionary:
csv_content = {
"motor_temp_1": "15m",
...
"variable_x": "24h"
}
The script communicates cyclically with other devices to read the current values of the variables found at csv_content.. For each value, the script should calculate the average and save the average values on a DB. So for instance, I read every 1 second the temperature of motor 1 (motor_temp_1) and save the average temperature for 15 minutes. For this I've written a Class:
class Average:
def __init__(self, name, type):
self.name = name
self.type = type
self.avg = 0
def read_sample(self, current_value):
# code for calculating average across the given time
return self.avg
How can I dynamically create Instances of the class Average from the strings found in csv_content? And then access their respective read_sample method when reading the values from the external devices?
# Create instances of Average class (QUESTION 1)
for key in csv_content:
instance_named_after_key_string = Average(key, csv_content[key])
# so I'm expecting something like:
# motor_temp_1 = Average("motor_temp_1", "15m")
# tank_pressure_1 = Average("tank_pressure_1", "15m")
# etc..
# Script for getting current values every 1 second and letting these values go through their Method for calculating average, the current values are being saved on another dictionary
while True:
# Communicate with external devices and get current_values
current_values = {
"motor_temp_1": 15.23,
"tank_pressure_1" : -21.1,
...
"variable_x": 0.23
}
# calculate average for each of the current_values (QUESTION 2)
for key in current_values:
instance_named_after_key_string.read_sample(current_values[key])
# so I'm expecting something like:
# motor_temp_1.read_sample(15.23)
# tank_pressure_1.read_sample(-21.1)
# etc..
# Print (Save to DB) every 15 minutes
if ( fifteen_minutes_have_passed):
for key in current_values:
print(instance_named_after_key_string.avg)
time.sleep(1)
Is this even possible? If not, what can I do to solve my problem?
Instead of trying to create variables named after the string values that hold the class instance, you could create a dictionary that holds the instances.
The keys to the dictionary would be the strings from the csv content and the value would be the instance of the class Average that you want to correspond to those strings.

Python: Data-structure and processing of GPS points and properties

I'm trying to read data from a csv and then process it on different way. (For starter just the average)
Data
(OneDrive) https://1drv.ms/u/s!ArLDiUd-U5dtg0teQoKGguBA1qt9?e=6wlpko
The data looks like this:
ID; Property1; Property2; Property3...
1; ....
1; ...
1; ...
2; ...
2; ...
3; ...
...
Every line is a GPS point. All points with same ID together (for example 1) produce one Route. The routes are not of the same length and some IDs are skipped. So it isn't a seamless increase of numbers.
I may need to add, that the points are ALWAYS the same set of meters apart from each other. And I don't need the XY information currently.
Wanted Result
In the end I want something like this:
[ID, AVG_Property1, AVG_Property2...] [1, 1.00595, 2.9595, ...] [2,1.50606, 1.5959, ...]
What I got so far
import os
import numpy
import pandas as pd
data = pd.read_csv(os.path.join('C:\\data' ,'data.csv'), sep=';')
# [id, len, prop1, prop2, ...]
routes = numpy.zeros((data.size, 10)) # 10 properties
sums = numpy.zeros(8)
nr_of_entries = 0;
current_id = 1;
for index, row in data.iterrows():
if(int(row['id']) != current_id): #after the last point of the route
routes[current_id-1][0] = current_id;
routes[current_id-1][1] = nr_of_entries; #how many points are in this route?
routes[current_id-1][2] = sums[0] / nr_of_entries;
routes[current_id-1][3] = sums[1] / nr_of_entries;
routes[current_id-1][4] = sums[2] / nr_of_entries;
routes[current_id-1][5] = sums[3] / nr_of_entries;
routes[current_id-1][6] = sums[4] / nr_of_entries;
routes[current_id-1][7] = sums[5] / nr_of_entries;
routes[current_id-1][8] = sums[6] / nr_of_entries;
routes[current_id-1][9] = sums[7] / nr_of_entries;
current_id = int(row['id']);
sums = numpy.zeros(8)
nr_of_entries = 0;
sums[0] += row[3];
sums[1] += row[4];
sums[2] += row[5];
sums[3] += row[6];
sums[4] += row[7];
sums[5] += row[8];
sums[6] += row[9];
sums[7] += row[10];
nr_of_entries = nr_of_entries + 1;
routes
My problem
1.) The way I did it, I have to copy paste the same code for every other processing approach, since as stated I need to do multiple different way. Average is just an example.
2.) The reading of the data is clumsy and fails when IDs are missing
3.) I'm a C# Developer, so my approach would be to create a Class 'Route' which has all the points and then provide methods for 'calculate average for prop 1'. Or something. This way I could also tweak the data if needed. (extreme values for example). But I have no idea how this would be done in Phyton and if this is a reasonable approach in this language.
4.) Is there a more elegant way to iterate through the original csv and getting like Route ID 1, then Route ID 2 and so on? Maybe something like LINQ Queries in C#?
Thanks for any help.
He is a solution and some ideas you can use. The example features multiple options for the same issue so you have to choose which fits the purpose best. Also it is Python 3.7, you didn't specify a version so i hope this works.
class Route(object):
"""description of class"""
def __init__(self, id, rawdata): # on startup
self.id = id
self.rawdata = rawdata
self.avg_Prop1 = self.calculate_average('Prop1')
self.sum_Prop4 = None
def calculate_average(self, Prop_Name): #selfreference for first argument in class method
return self.rawdata[Prop_Name].mean()
def give_Prop_data(self, Prop_Name): #return the Propdata as list
return self.rawdata[Prop_Name].tolist()
def any_function(self, my_function, Prop_Name): #not sure what dataframes support so turning it into a list first
return my_function(self.rawdata[Prop_Name].tolist())
#end of class definiton
data = pd.read_csv('testdata.csv', sep=';')
# [id, len, prop1, prop2, ...]
route_list = [] #List of all the objects created from the route class
for i in data.id.unique():
print('Current id:', i,' with ',len(data[data['id']==i]),'entries')
route_list.append(Route(i,data[data['id']==i]))
#created the Prop1 average in initialization of route so just accessing attribute
print(route_list[1].avg_Prop1)
for current_route in route_list:
print('Route ',current_route.id , ' Properties :')
for i in current_route.rawdata.columns[1:]: #for all except the first (id)
print(i, ' has average ', current_route.calculate_average(i)) #i is the string of the column not just an id
#or pass any function that you want
route_list[1].sum_Prop4 = (route_list[1].any_function(sum,'Prop4'))
print(route_list[1].sum_Prop4)
#which is equivalent to
print(sum(route_list[1].rawdata['Prop4']))
To adress your individual problems out of order:
For 2. and 4.) Looping only over the existing Ids (data.id.unique()) solves the problem. I have no idea what LINQ Queries are, but i assume they are similar. In general, Python has a great way of looping over objects (like for current_route in route_list), which is worth looking into if you want to use it a little more.
For 1. and 3.) Again looping solves the issue. I created a class in the example, mostly to show the syntax for classes. The benefits and drawbacks for using classes should be the same in Python as in C#.
As it is right now the class probably isn't great, but this depends on how you want to use it. If the class should just be a practical way of storing and accessing data it shouldn't have the methods, because you don't need an individual average method for each route. Then you can just access it's data and use it in a function like in sum(route_list[1].rawdata['Prop4']). If however, depending on the data (amount of rows for example) different calculations are necessary, it might come in handy to use the method calculate_average and differentiate in there.
An other example would be the use of the attributes. If you need the average for Prop1 every time, creating it at the initialization sees a good idea, otherwise i wouldn't bother always calculating it.
I hope this helps!

How do I extract stress/strain at sectionpoints using abaqus python script?

I have this code:
def get_field(odb, step, frame, field, element):
if field == 'E':
function = get_strain
for f in odb.steps[step].frames[frame].fieldOutputs[field].getSubset(region=element_set).values:
data = function(f.data)
dict_data[index] = data
index += 1
return dict_data
I want to include section points and section category. What should I change in this code to achieve that?
You need to use another getSubset:
fo = ..... fieldOutput object
f = fo.getSubset(sectionPoint=sp)
Section point objects can be found in the odb:
odbname = 'mine.odb'
odb = session.odbs[odbname]
sp = odb.sectionCategories.values()[0]
If you want a particular section point number, each section Point object has the property
sp.number

Dataflow job is timing out. Having issues comparing two collections, and appending the values of one to another.

Hoping someone can help me here. I have two bigquery tables that I read into 2 different p collections, p1 and p2. I essentially want to update product based on a type II transformation that keeps track of history (previous values in the nested column in product) and appends new values from dwsku.
The idea is to check every row in each collection. If there is a match based on some table values (between p1 and p2), then check product's nested data to see if it contains all values in p1 (based on it's sku number and brand). If it does not contain the most recent data from p2 then take a copy of the format of the current nested data in product, and fit the new data into it. Take this nested format and add it to the existing nested products in product.
def process_changes(element, productdata):
for data in productdata:
if element['sku_number'] == data['sku_number'] and element['brand'] == data['brand']:
logging.info('Processing Product: ' + str(element['sku_number']) + ' brand:' + str(element['brand']))
datatoappend = []
for nestline in data['product']:
logging.info('Nested Data: ' + nestline['product'])
if nestline['in_use'] == 'Y' and (nestline['sku_description'] != element['sku_description'] or nestline['department_id'] != element['department_id'] or nestline['department_description'] != element['department_description']
or nestline['class_id'] != element['class_id'] or nestline['class_description'] != element['class_description'] or nestline['sub_class_id'] != element['sub_class_id'] or nestline['sub_class_description'] != element['sub_class_description'] ):
logging.info('we found a sku we need to update')
logging.info('sku is ' + data['sku_number'])
newline = nestline.copy()
logging.info('most recent nested product element turned off...')
nestline['in_use'] = 'N'
nestline['expiration_date'] = "%s-%s-%s" % (curdate.year, curdate.month, curdate.day) # CURRENT DATE
logging.info(nestline)
logging.info('inserting most recent change in dwsku inside nest')
newline['sku_description'] = element['sku_description']
newline['department_id'] = element['department_id']
newline['department_description'] = element['department_description']
newline['class_id'] = element['class_id']
newline['class_description'] = element['class_description']
newline['sub_class_id'] = element['sub_class_id']
newline['sub_class_description'] = element['sub_class_description']
newline['in_use'] = 'Y'
newline['effective_date'] = "%s-%s-%s" % (curdate.year, curdate.month, curdate.day) # CURRENT DATE
newline['modified_date'] = "%s-%s-%s" % (curdate.year, curdate.month, curdate.day) # CURRENT DATE
newline['modified_time'] = "%s:%s:%s" % (curdate.hour, curdate.minute, curdate.second)
nestline['expiration_date'] = "9999-01-01"
datatoappend.append(newline)
else:
logging.info('Nothing changed for sku ' + str(data['sku_number']))
for dt in datatoappend:
logging.info('processed sku ' + str(element['sku_number']))
logging.info('adding the changes (if any)')
data['product'].append(dt)
return data
changed_product = p1 | beam.FlatMap(process_changes, AsIter(p2))
Afterwards I want to add all values in p1 not in p2 in a nested format as seen in nestline.
Any help would be appreciated as I'm wondering why my job is taking hours to run with nothing to show. Even the output logs in dataflow UI don't show anything.
Thanks in advance!
This can be quite expensive if side input PCollection p2 is large. From your code snippets it's not clear how PCollection p2 is constructed. But if it is, for example, a text file that is if size 62.7MB, processing it per element can be pretty expensive. Can you consider using CoGroupByKey: https://beam.apache.org/documentation/programming-guide/#cogroupbykey
Also note that from a FlatMap, you are supposed to return a iterator of elements from the processing method. Seems like you are returning a dictionary('data') which probably is incorrect.

Maya UI Python change NumberOfCollums dynamically

I want to change (kind of dynamically) the NumberOfColumns of a rowColumnLayout inside a Maya Window. Depending on the value given by 'SLiBThumbSizeComboBox' i want to change the count for the columns.
Here is the problem: when running my 2 functions inside the Script Editor everything is working fine. I execute the first one - the ScrollLayout is created. I execute the second and the rowColumnLayout is created with the right count of columns.
But when I try run it only by the first function, meaning the second function is called at the end of the first one - it's not working anymore?! I get the error message, that NumberOfCollumns has to be greater than 0 ?!
def FunctionA():
if cmds.scrollLayout('SLiBScrollLayout', query = True, exists = True):
cmds.deleteUI('SLiBScrollLayout', layout = True)
cmds.scrollLayout('SLiBScrollLayout', p="SLiB_thumbsframe")
def FunctionB():
iconLayout = cmds.optionMenu('SLiBThumbSizeComboBox', query = True, value = True)
iconSize = iconLayout.split('x')
iconDiv = int(iconSize[0])
n = int(cmds.scrollLayout("SLiBScrollLayout", query=True, saw=1)/iconDiv)
cmds.rowColumnLayout('Icons', numberOfColumns=n, p="SLiBScrollLayout")
Thanks in advance
Daniel
I'm not surprised the rowColumnlayout complains if you give it zero columns: you'll always need 1. Depending on how the are setting up the gui , your query on saw might return 0, which would explain your problem.
Here's a very basic example of what it looks like your trying to do:
w = cmds.window()
c = cmds.columnLayout(adj=True)
v_slider = cmds.intSlider(min = 1, max =10, value=2)
h_slider = cmds.intSlider(min = 1, max =10, value=2)
scroll = cmds.scrollLayout()
form = cmds.formLayout()
def update_row(*_):
# get the row and column counts
rows = cmds.intSlider(v_slider, q=True, v= True)
columns = cmds.intSlider(h_slider, q=True, v= True)
# delete the old layout and rebuild.
# the 'or []` below lets you loop even if there are no children....
for n in cmds.formLayout(form, q=True, ca=True) or []:
cmds.deleteUI(n)
cmds.setParent(form)
# make a new rowColumn
new_row = cmds.rowColumnLayout(nc = columns)
for n in range(rows * columns):
cmds.button(label="button_%i" % n)
cmds.formLayout(form, e=True, af = [(new_row,'top',0), (new_row, 'bottom', 0 ), (new_row, 'left', 0 ), (new_row, 'right', 0)])
# both sliders call the update function
cmds.intSlider(h_slider, e=True, cc =update_row)
cmds.intSlider(v_slider, e=True, cc =update_row)
update_row() # do it once to get started
cmds.showWindow(w)
The key here is the order in which it's declared: the function knows what v_slider, h_slider and form are because it's declared after them and doesn't need to do extra work to find them (you can get a more controlled version of the same effect with a class. You'll notice I don't use the names at all: names are unreliable if there's an old layout lying around, it's simpler to use variables.
I've also set the minimum values for the row and columns to 1 so there's no zero division problem.

Categories

Resources