Defining variables in a loop based on a dictionary - python

I am converting DICOMs to PNGs with Python 3.x and Pydicom. There are occasional errors when reading DICOM header tags, causing the script to crash. Until now, I worked around it by using exceptions like below:
try: studyd = ds.StudyDate
except: studyd = ''
pass
...
This repetitive approach lengthens the code.
Unfortunately, I fail optimizing the code by defining a dictionary containing the Pydicom header and the target variable and looping through it. How could I do this with something like:
ds = pydicom.dcmread()
tags = { 'StudyDate': 'studyd', 'Modality': 'modal', 'PatientName': 'patname', etc.}
for key, val in tags.items():
...

Try this:
ds = pydicom.dcmread()
tags = { 'StudyDate': 'studyd', 'Modality': 'modal', 'PatientName': 'patname', etc.}
header_dict = dict()
for key, val in tags.items():
header_dict[val] = getattr(ds, key)
print(header_dict)
Using the getattr to get the header value and storing it in a dict against the specified name

Related

How to pass the structure of a dictionary into a function

I am trying to pass a dictionary that was created automatically into a function that defines the scheme of a JSON.
This is my function:
def split_line_items(df_transactions):
for row in df_transactions.itertuples():
yield {
"count_0": row.count_0,
"count_1": row.count_1,
"count_2": row.count_2,
"total_count": row.total_count
}
and this is my dictionary:
d = {'"count_0"': 'row.count_0',
'"count_1"': 'row.count_1',
'"count_2"': 'row.count_2',
'"total_count"': 'row.total_count'}
How can I pass the dictionary into the function without having to modify it manually?
EDIT: I don't want to use the data contained in the dictionary, I want to use the structure (key/values) from the dictionary to define a JSON. The example in yield {} is how it should look like.
I guess you mean something like this, however the question is not very clear.
# considering this is your tf_transactions
transactions = namedtuple('r',['count_0', 'count_1', 'count_2', 'total_count'])
tf_transactions = [transactions(1,2,3,4), transactions(1,2,3,4)]
for row in tf_transactions:
yield {k.strip('\"'): getattr(row, v.split('.')[1]) for k,v in d.items()}

Append multiple json request as list

I can't seems to wrap my head around this silly issue. There are API requests that run simultaneously 23 different section stored in a dictionary :
polygonsDict = {
'Sect1':'100,6.3',
'Sect2':'100,6.0',
'Sect3':'100,5.5' # and more sections
}
urlDict = {
'traffic': 'https://google.com'
}
Here is the code where I iteratively :
section_key = list(polygonsDict.keys()) #convert the dictionary key to list for iteration
for idx, section in enumerate(section_key):
traffics(section ,urlDict['traffic']+polygonsDict[section]).getPolygonTraffics() #This line is constructing the link for request.
Then, the link is send to a class called traffics with getPolygonTraffics function :
class traffics:
def __init__(self, name, traffics):
self.traffics = traffics
self.name = name
def getPolygonTraffics(self):
try :
print("TRF: Running for "+self.name+"...")
raw = req.get(self.traffics).json()
traffics_raw = [raw] #wrap the dict to list
traffics_ls = []
for ls in traffics_raw:
traffics_ls.append(ls)
#Melt the list of dictionary to form a DataFrame
traffics_df = pd.DataFrame(traffics_ls).explode('jams').reset_index(drop=True)
print(traffics_df)
#exception when `jams` is not found in the list of dict.
except KeyError:
print("Skip!")
In getPolygonTraffics, I want to append every traffics_raw (the json requests) to one individual list and eventually, explode them to a dataFrame. How can I achieve this? I'm not very sure how to explain this.
Current output is multiple lists of each dictionary :
[{}]
[{}]
WHat I want is : [{},{},{}]. Then explode to DataFrame.

How can I append values from a JSON dictionary to a new list?

I have a .json file of all of my AWS target groups. This was created using aws elbv2 describe-target-groups. I want to extract every TargetGroupArn from this file and store it into a Python list.
With my current code, I get no output. I can confirm that the dictionary has data in it, but nothing is being appended to the list that I'm trying to create.
import json
from pprint import pprint
with open('target_groups.json') as f:
data = json.load(f)
items = data['TargetGroups']
arn_list = []
for key, val in data.items():
if key == 'TargetGroupArn':
arn_list.append(val)
print(arn_list)
Expected results would be for arn_list to print out looking like this:
[arn:aws:elb:xxxxxxx:targetgroup1, arn:aws:elb:xxxxxxx:targetgroup2, arn:aws:elb:xxxxxxx:targetgroup3]
Change your code to this:
import json
from pprint import pprint
with open('target_groups.json') as f:
data = json.load(f)
arn_list = []
if 'TargetGroups' in data:
items = data['TargetGroups']
for item in items:
if 'TargetGroupArn' in item:
arn_list.append(item['TargetGroupArn'])
print(arn_list)
else:
print('No data')
There are many ways to make this python code more concise. However, I prefer a more wordy style that easier to read.
Also note that this code checks that keys exist so that the code will not stackdump for missing data.
it would be better if you could post the file you are trying to get data from, but this part:
for key, val in data.items():
if key == 'TargetGroupArn':
arn_list.append(val)
need to be changed to:
for key, val in items.items():
if key == 'TargetGroupArn':
arn_list.append(val)
you get data from 'data' and add it to items, but you never actually used it.
give it a shot.

TypeError('list indices must be integers, not str',) with get() method in Python

I am trying to convert JSON files to CSV using below code. The PARENT_ID and PARENT_TYPE fields can be NULL most of the times. If I use result["parent"]["id"] it returns KeyError. That's why I thought of using get() to return whatever value they hold. But I am getting TypeError('list indices must be integers, not str',) for these fields. Can anyone suggest any workaround?
Thanks in advance!
"parent" is a list within "result" dict.
my_dict_list =[]
try:
for f in os.listdir(file_dir):
if f.endswith('.json') and f.startswith('folders_'):
file_path = os.path.join(file_dir, f)
data = open(file_path, 'r')
for line in data:
my_dict = {}
parsed_data = json.loads(line)
my_dict["REQUEST_ID"] = parsed_data["requestId"]
my_dict["SUCCESS"] = parsed_data["success"]
for result in parsed_data["result"]:
my_dict["NAME"] = result["name"]
my_dict["DESCRIPTION"] = result["description"]
my_dict["FOLDER_ID"] = result["folderId"]["id"]
my_dict["FOLDER_ID_TYPE"] = result["folderId"]["type"]
my_dict["FOLDER_TYPE"] = result["folderType"]
my_dict["PARENT_ID"] = result.get(["parent"]["id"])
my_dict["PARENT_TYPE"] = result.get(["parent"]["type"])
Currently you are trying to access the member "id" from a list with the string "parent" in the following line:
my_dict["PARENT_ID"] = result.get(["parent"]["id"])
You have to check if the result dict contains the key "parent".
The get method of your result dict can be used for this.
It returns None if the dict does not contain the key "parent".
Otherwise use the get method and try to get the id of the parent
Your code has to be
my_dict["PARENT_ID"] = result["parent"].get("id") if result.get("parent") else None

Define a dictionary name within a function

I am writing a function that will take a parameter and, among other things, make a dictionary. I would like the dictionary's name to be based off the name of the input file. Say ht input file is input.xml , i would like the name of the dictionary to be input. Ideally I would use something like this:
def function(input):
for x in y: list(get value)
input[:4][key] = [value]
I am wondering if you know a better way to do this but what i am using now is an extra name in the function:
def function(input, dictname):
for x in y: list(get value)
dictname[key] = [value]
right now I am simply adding a second name to my function but am wondering if there is a way to do this to require fewer inputs.
Edit
I am including a longer version of the function I am using so you guys can get the context. This uses a BioPython module to iterate through an XML file of hits. I am using [temp] to hold the hits for each query and then making a dictionary of for each set of query/hits. I would like this dictionary to be named the same as my input file.
from Bio.Blast import NCBIXML
def make_blast_dictionary(blastxml, maxhits, blastdict):
temp=[]
for record in NCBIXML.parse(open(blastxml):
for number, align in enumerate(record.alignments):
if number == int(maxhits): break
temp.append(str(align.title).split("|")[1])
blastdict[str(record.query_id)] = [temp]
The thing about named variables is that you can call them whatever you like. It's best to name them specific to the context you're using them with.
It would be a better move to simply return a dictionary from your method, instead.
The other respondents are legitimately concerned about why you would want to do this or whether you should do this. That being said, here is how you could do it:
import os.path
def function(filename):
d = {'red': 10, 'blue': 20}
name, ext = os.path.splitext(filename)
globals()[name] = d
function('input.xml')
print input
def make_name(input):
return = input.split('.')[0]
def function(input):
"""Note: this function is incomplete and assumes additional parameters are in your original script
"""
for x in y: list(get value)
dict_name[key] = [value]
return dict_name
def make_dict(input):
dict_name = make_name(input)
dict_name = {}
dict_name = function(input)
return dict_name
Is this what you need?

Categories

Resources