Read values from .csv file based on user input - python

I am making a pokedex where the names and stats of pokemon are stored in a .csv file, based on user input it should read the .csv and output the values that are paired with it. If the user inputs the name "pikachu" it should read all the stats and display them:
25,"pikachu",25,4,60,112,"electric",NA,55,40,35,50,50,90,"static",NA,"lightning-rod","#F8D030",NA,NA,"ground","fairy","25.png",1,172,10,8,"quadruped"
but instead of this it just outputs the image, the code is below:
import pandas as pd
import matplotlib.pyplot as plt
import os
import glob
import natsort
# reading the images dataset
dir1 = r"G:\pythonProject\pokemon_images" #73
path1 = os.path.join(dir1, '*g')
files = glob.glob(path1)
files1 = natsort.natsorted(files, reverse=False)
imag = []
for x in files1:
img = plt.imread(x)
imag.append(img)
# reading the details dataset
data = pd.read_csv('pokemon.csv')
print("Pokedex\n")
print("Welcome Pokemon Lovers\n")
print("Search for a pokemon\n")
df1 =input("<A>Search by pokemon name\n<B>Search by pokemon ID\n(select A or B)\n")
df1.upper()
if(df1=="A"):
print("Enter the name of the pokemon")
name = input()
name.lower().strip()
dt = data[:].where(data['pokemon']==name)
st = dt[dt['id'].notnull()]
idx = dt.index[dt['pokemon'] == name]
if idx > 721:
exit(0)
plt.imshow(imag[idx[-1]])
plt.axis("off") # turns off axes
plt.axis("tight") # gets rid of white border
plt.axis("image") # square up the image instead of filling the "figure" space
plt.show()
elif(df1=="B"):
print("Enter the ID of the pokemon")
ID = int(input())
tt = data[:].where(data['id']==ID)
idx1 = tt.index[tt['id']==ID]
qt = tt[tt['id'].notnull()]
for i in qt.columns:
print(i," : ",qt[i][idx1[-1]])
if idx1>721:
exit(0)
plt.imshow(imag[idx1[-1]])
plt.axis("off") # turns off axes
plt.axis("tight") # gets rid of white border
plt.axis("image") # square up the image instead of filling the "figure" space
plt.show()

Related

MatPlot lib keeps giving "out of range error"

Im trying to make a pokedex where it stores all the names and stats of the pokemon in a .csv file and reads off of that when called. It should also show an image of the pokemon when called.
The code is as follows:
import pandas as pd
import matplotlib.pyplot as plt
import os
import glob
import natsort
# reading the images dataset
dir1 = r"C:\Users\yash1\Desktop\pokedex\pokemon_images"
path1 = os.path.join(dir1, '*g')
files = glob.glob(path1)
files1 = natsort.natsorted(files, reverse=False)
imag = []
for x in files1:
img = plt.imread(x)
imag.append(img)
# reading the details dataset
data = pd.read_csv('pokemon.csv')
print("Pokedex\n")
print("Welcome Pokemon Lovers\n")
print("Search for a pokemon\n")
df1 =input("<A>Search by pokemon name\n<B>Search by pokemon ID\n(select A or B)\n")
df1.upper()
if(df1=="A"):
print("Enter the name of the pokemon")
name = input()
name.lower().strip()
dt = data[:].where(data['pokemon']==name)
st = dt[dt['id'].notnull()]
idx = dt.index[dt['pokemon'] == name]
if idx > 721:
exit(0)
plt.imshow(imag[idx[1]])
plt.axis("off") # turns off axes
plt.axis("tight") # gets rid of white border
plt.axis("image") # square up the image instead of filling the "figure" space
plt.show()
elif(df1=="B"):
print("Enter the ID of the pokemon")
ID = int(input())
tt = data[:].where(data['id']==ID)
idx1 = tt.index[tt['id']==ID]
qt = tt[tt['id'].notnull()]
for i in qt.columns:
print(i," : ",qt[i][idx1[0]])
if idx1>721:
exit(0)
#plt.imshow(imag[idx1[0]])
plt.axis("off") # turns off axes
plt.axis("tight") # gets rid of white border
plt.axis("image") # square up the image instead of filling the "figure" space
plt.show()
when I run it it gives me an error like this:
Traceback (most recent call last):
File "G:/pythonProject/main.py", line 33, in <module>
plt.imshow(imag[idx[1]])
File "C:\python\lib\site-packages\pandas\core\indexes\base.py", line 4604, in __getitem__
return getitem(key)
IndexError: index 1 is out of bounds for axis 0 with size 1
How do I fix the axis bounds, I even replaced the brackets with "0" and it still didn't work.

How to merge multiple MODIS swaths into one plot in python?

I want to mosaic/merge multiple swaths of the MODIS dataset (MOD06_L2) using python. I used the example (http://hdfeos.org/zoo/MORE/LAADS/MOD/MOD04_L2_merge.py) to read multiple files and merge. But I am getting an error while doing so, how to correct this error?
I would like to know is there any better way than this, to merge/mosaic MODIS HDF files into one?
import os
import glob
import matplotlib as mpl
import matplotlib.pyplot as plt
# import cartopy.crs as ccrs
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
# The first file in 3 swath files.
FILE_NAME = 'MOD06_L2.A2017126.0655.061.2019226193408.hdf'
GEO_FILE_NAME ='MOD06_L2.A2017126.0655.061.2019226193408.hdf'
DATAFIELD_NAME = 'Brightness_Temperature'
from pyhdf.SD import SD, SDC
i = 0
for file in list(glob.glob('MOD06*.hdf')):
reader = open(file)
hdf = SD(file, SDC.READ)
# Read dataset.
data2D = hdf.select(DATAFIELD_NAME)
data = data2D[:,:].astype(np.double)
hdf_geo = SD(GEO_FILE_NAME, SDC.READ)
# Read geolocation dataset.
lat = hdf_geo.select('Latitude')
latitude = lat[:,:]
lon = hdf_geo.select('Longitude')
longitude = lon[:,:]
# Retrieve attributes.
attrs = data2D.attributes(full=1)
lna=attrs["long_name"]
long_name = lna[0]
aoa=attrs["add_offset"]
add_offset = aoa[0]
fva=attrs["_FillValue"]
_FillValue = fva[0]
sfa=attrs["scale_factor"]
scale_factor = sfa[0]
vra=attrs["valid_range"]
valid_min = vra[0][0]
valid_max = vra[0][1]
ua=attrs["units"]
units = ua[0]
invalid = np.logical_or(data > valid_max,data < valid_min)
invalid = np.logical_or(invalid, data == _FillValue)
data[invalid] = np.nan
data = (data - add_offset) * scale_factor
datam = np.ma.masked_array(data, np.isnan(data))
if i == 0 :
data_m = datam
latitude_m = latitude
longitude_m = longitude
else:
data_m = np.vstack([data_m, datam])
latitude_m = np.vstack([latitude_m, latitude])
longitude_m = np.vstack([longitude_m, longitude])
i = i + 1
m = Basemap(projection='cyl', resolution='l',
llcrnrlat=-90, urcrnrlat=90,
llcrnrlon=-180, urcrnrlon=180)
m.drawcoastlines(linewidth=0.5)
m.drawparallels(np.arange(-90, 91, 45))
m.drawmeridians(np.arange(-180, 180, 45), labels=[True,False,False,True])
sc = m.scatter(longitude_m, latitude_m, c=data_m, s=0.1, cmap=plt.cm.jet,
edgecolors=None, linewidth=0)
cb = m.colorbar()
cb.set_label(units)
# Put title using the first file.
basename = os.path.basename(FILE_NAME)
plt.title('{0}\n{1}'.format(basename, DATAFIELD_NAME))
fig = plt.gcf()
# Save image.
pngfile = "{0}.py.png".format(basename)
fig.savefig(pngfile)
It showing an error
ValueError: 'c' argument has 4604040 elements, which is inconsistent with 'x' and 'y' with size 657720.

How to add an image to PDF using Python and create a report from esri geodatabase tables

I have an old script that uses SSReport to create and generate a PDF adding some basic data. I want to update it to include an image file and loop through some esri geodatabase tables. I don't see much documentation on the SSReport library, using 2.7. Is there a newer/better way?
I don't want to have to install 3rd party package, if possible.
import SSReport as REPORT
pdfOutput = REPORT.openPDF(fileName)
#Set up Table
NumColumns = 4
report = REPORT.startNewReport(NumColumns,
title = 'Report ',
landscape = False,
numRows = "", # probably empty
titleFont = REPORT.ssTitleFont)
grid = report.grid
grid.writeCell((grid.rowCount, 1),"hello world",justify = "left",)
grid.finalizeTable() # Will fill empty rows with spaces.
report.write(pdfOutput) # write to PDF
Overall I wanted to create a PDF report that included a map, and image and some tabular data stored in an Esri geodatabase. Due to lack of info on the above methods and time crunch, I ended up relying on arcpy.Mapping to update map layers elements including an image and export the layout.
I used MatplotLib to generate additional charts and tables since there are many examples and threads to assist. As well comes installed with ArcGIS Desktop and Server to avoid having a prerequisite to install 3rd party libs for a client.
Here is the sample:
import matplotlib.pyplot as plt
import xlrd
import xlwt
import datetime
import os
import glob
import arcpy
import SSReport as REPORT
import numpy as NUM
from matplotlib.backends.backend_pdf import PdfPages as PDF
import matplotlib.pyplot as PLT
# get path for mxd template from location of script
filePath = os.path.dirname(os.path.abspath(__file__))
templatePath = os.path.join(filePath,"templates")
def TabletoPDF2(outdir, outputPDF):
tables = [os.path.join(outdir,'scratch.gdb', 'table1'),
os.path.join(outdir, 'scratch.gdb', 'table2')]
pp = PDF(outputPDF)
for table in tables:
# convert to format for creating charts.
ntab = arcpy.da.TableToNumPyArray(table, "*")
columns = [fld for fld in ntab.dtype.names if fld not in ["OBJECTID"]]
cell_text = []
for row in ntab.tolist():
cell_text.append(row[1:])
fig = PLT.figure(figsize=(8.2, 10.6))
# Create PIECHART (percent lengeth)
ax1 = PLT.subplot(211)
data = ntab["percent_len"].tolist()
vals = [x for x in data if x > 0.]
labels = ntab[columns[0]].tolist()
labels = [n for n, v in zip(labels, data) if v > 0]
ax1.pie(vals, autopct='%1.1f%%', shadow=True, startangle=90)
ax1.axis('equal')
ax1.legend(labels, loc='center right', fontsize=8, bbox_to_anchor=(1, 1))
# Create TABLE of values
ax2 = PLT.subplot(212)
the_table = PLT.table(cellText=cell_text, colLabels=columns, loc='center')
the_table.auto_set_font_size(True)
PLT.axis('off')
PLT.tight_layout()
#### Set Title ####
title = os.path.basename(table)
PLT.suptitle(title, fontsize=11, fontweight='bold')
pp.savefig(fig)
pp.close()
return outputPDF
def CreatePDFReport(sPath, outprofilegraph, sfroute_feat):
template_mxd_filename = os.path.join(templatePath,'Reportemplate.mxd')
layoutpdf_filename = os.path.join(sPath,'Layout.pdf')
tablepdf_filename = os.path.join(sPath,'TableReport.pdf')
finalpdf_filename = os.path.join(sPath,'Final Report.pdf')
#Create layout report (page1)
arcpy.AddMessage("Creating Layout...")
arcpy.AddMessage(template_mxd_filename)
mxd = arcpy.mapping.MapDocument(template_mxd_filename)
change_picture_element(mxd, outprofilegraph)
change_layer_source(mxd, sfroute_feat)
arcpy.mapping.ExportToPDF(mxd,layoutpdf_filename)
# Create Table Report(page2)
TablePDF = CreateTableReport(tablepdf_filename)
TablePDF = TabletoPDF2(sPath, tablepdf_filename)
#Create Final report (merge)
msg = ("Creating Output Report {}".format(finalpdf_filename))
arcpy.AddMessage(msg)
if os.path.exists(finalpdf_filename):
os.remove(finalpdf_filename)
pdfFinal = arcpy.mapping.PDFDocumentCreate(finalpdf_filename)
pdfFinal.appendPages(layoutpdf_filename)
pdfFinal.appendPages(TablePDF)
pdfFinal.saveAndClose()
os.remove(tablepdf_filename)
os.remove(layoutpdf_filename)
return finalpdf_filename
def change_layer_source(mxd, route_feat):
""" Update layer datasource and zoom to extent """
arcpy.AddMessage(route_feat)
replace_workspace_path, datasetname = os.path.split(route_feat)
df = arcpy.mapping.ListDataFrames(mxd)[0]
for lyr in arcpy.mapping.ListLayers(mxd, data_frame=df):
if lyr.name == 'RouteLayer':
lyr.replaceDataSource (replace_workspace_path, "None")
ext = lyr.getExtent()
df.extent = ext
# mxd.save()
def change_picture_element(mxd, outprofilegraph):
for elm in arcpy.mapping.ListLayoutElements(mxd, "PICTURE_ELEMENT"):
if elm.name == "elevprofile":
elm.sourceImage = outprofilegraph
# mxd.save()
if __name__ == '__main__':
folderPath = arcpy.GetParameterAsText(0)
inTable = arcpy.GetParameterAsText(1)
sfroute_feat = arcpy.GetParameterAsText(2)
finalReport = CreatePDFReport(folderPath, outprofilegraph, sfroute_feat)
# Set outputs
arcpy.SetParameterAsText(4, finalReport)

updating a Slider min - max range in runtime in matplotlib [duplicate]

I am trying to write a small bit of code that interactively deletes selected slices in an image series using matplotlib. I have created a button 'delete' which stores a number of indices to be deleted when the button 'update' is selected. However, I am currently unable to reset the range of my slider widget, i.e. removing the number of deleted slices from valmax. What is the pythonic solution to this problem?
Here is my code:
import dicom
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
frame = 0
#store indices of slices to be deleted
delete_list = []
def main():
data = np.random.rand(16,256,256)
nframes = data.shape[0]
raw_dicom_stack = []
for x in range (nframes):
raw_dicom_stack.append(data[x,:,:])
#yframe = 0
# Visualize it
viewer = VolumeViewer(raw_dicom_stack, nframes)
viewer.show()
class VolumeViewer(object):
def __init__(self, raw_dicom_stack, nframes):
global delete_list
self.raw_dicom_stack = raw_dicom_stack
self.nframes = nframes
self.delete_list = delete_list
# Setup the axes.
self.fig, self.ax = plt.subplots()
self.slider_ax = self.fig.add_axes([0.2, 0.03, 0.65, 0.03])
self.delete_ax = self.fig.add_axes([0.85,0.84,0.1,0.04])
self.update_ax = self.fig.add_axes([0.85,0.78,0.1,0.04])
self.register_ax = self.fig.add_axes([0.85,0.72,0.1,0.04])
self.add_ax = self.fig.add_axes([0.85,0.66,0.1,0.04])
# Make the slider
self.slider = Slider(self.slider_ax, 'Frame', 1, self.nframes,
valinit=1, valfmt='%1d/{}'.format(self.nframes))
self.slider.on_changed(self.update)
#Make the buttons
self.del_button = Button(self.delete_ax, 'Delete')
self.del_button.on_clicked(self.delete)
self.upd_button = Button(self.update_ax, 'Update')
self.upd_button.on_clicked(self.img_update)
self.reg_button = Button(self.register_ax, 'Register')
self.add_button = Button(self.add_ax, "Add")
# Plot the first slice of the image
self.im = self.ax.imshow(np.array(raw_dicom_stack[0]))
def update(self, value):
global frame
frame = int(np.round(value - 1))
# Update the image data
dat = np.array(self.raw_dicom_stack[frame])
self.im.set_data(dat)
# Reset the image scaling bounds (this may not be necessary for you)
self.im.set_clim([dat.min(), dat.max()])
# Redraw the plot
self.fig.canvas.draw()
def delete(self,event):
global frame
global delete_list
delete_list.append(frame)
print 'Frame %s has been added to list of slices to be deleted' %str(frame+1)
print 'Please click update to delete these slices and show updated image series \n'
#Remove duplicates from delete list
def img_update(self,event):
#function deletes image stacks and updates viewer
global delete_list
#Remove duplicates from list and sort into numerical order
delete_list = list(set(delete_list))
delete_list.sort()
#Make sure delete_list is not empty
if not delete_list:
print "Delete list is empty, no slices to delete"
#Loop through delete list in reverse numerical order and remove slices from series
else:
for i in reversed(delete_list):
self.raw_dicom_stack.pop(i)
print 'Slice %i removed from dicom series \n' %(i+1)
#Can now remove contents from delete_list
del delete_list[:]
#Update slider range
self.nframes = len(self.raw_dicom_stack)
def show(self):
plt.show()
if __name__ == '__main__':
main()
In order to update a slider range you may set the min and max value of it directly,
slider.valmin = 3
slider.valmax = 7
In order to reflect this change in the slider axes you need to set the limits of the axes,
slider.ax.set_xlim(slider.valmin,slider.valmax)
A complete example, where typing in any digit changes the valmin of the slider to that value.
import matplotlib.pyplot as plt
import matplotlib.widgets
fig, (ax,sliderax) = plt.subplots(nrows=2,gridspec_kw=dict(height_ratios=[1,.05]))
ax.plot(range(11))
ax.set_xlim(5,None)
ax.set_title("Type number to set minimum slider value")
def update_range(val):
ax.set_xlim(val,None)
def update_slider(evt):
print(evt.key)
try:
val = int(evt.key)
slider.valmin = val
slider.ax.set_xlim(slider.valmin,None)
if val > slider.val:
slider.val=val
update_range(val)
fig.canvas.draw_idle()
except:
pass
slider=matplotlib.widgets.Slider(sliderax,"xlim",0,10,5)
slider.on_changed(update_range)
fig.canvas.mpl_connect('key_press_event', update_slider)
plt.show()
It looks like the slider does not have a way to update the range (api). I would suggest setting the range of the slider to be [0,1] and doing
frame = int(self.nframes * value)
On a somewhat related note, I would have made frame an instance variable a data attribute instead of a global variable (tutorial).

compare a single image with 10 or more images and find the matching one

when i run the program I need my code to :
initialize the camera
take a picture
request user to enter paths for the current image to be stored and the image to be compared to
detect edges of currently taken picture and save in database
compare current edge image to 10 or more edge images in database
output as the edge image that has highest match percentage with current edge image
basically its like an object identification program ... can someone please help me out ?
here is the code i have done so far
from itertools import izip
import numpy as np
import cv2
from matplotlib import pyplot as plt
from PIL import Image
def take_and_save_picture(im_save):
'''Take a picture and save it
Args:
im_save: filepath where the image should be stored
'''
camera_port = 0
ramp_frames = 30
cap = cv2.VideoCapture(camera_port)
def get_image():
retval, im = cap.read()
return im
for i in xrange(ramp_frames):
temp = get_image()
print("Taking image...")
# Take the actual image we want to keep
camera_capture = get_image()
#im_save_tmp = im_save + '.jpg'
im_save_tmp = im_save
# A nice feature of the imwrite method is that it will automatically choose the
# correct format based on the file extension you provide. Convenient!
cv2.imwrite(im_save_tmp, camera_capture)
# You'll want to release the camera, otherwise you won't be able to create a new
# capture object until your script exits
# del(cap)
img1 = cv2.imread(im_save_tmp, 0)
edges = cv2.Canny(img1, 100, 200)
cv2.imwrite(im_save, edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
#im1 = "/Users/Me/gop.jpg"
#im2 = "/Users/Me/aarthi.jpg"
im1 = input('enter the path of database file')
im2 = input('enter the path where captured image is to be saved')
#im1="/Users/Me/home1.png"
#im2="/Users/Me/home.png"
def compute_edges_diff(im1, im2):
'''Compute edges diff between to image files.
Args:
im1: filepath to the first image
im2: filepath to the second image
Returns:
float: percentage of difference between images
'''
#for no_file1 in range(0,10):
#template = cv2.imread('numbers1/{no_file}.png'.format(no_file=no_file1),0)
i1 = Image.open(im1)
i2 = Image.open(im2)
assert i1.mode == i2.mode, "Different kinds of images."
assert i1.size == i2.size, "Different sizes."
pairs = izip(i1.getdata(), i2.getdata())
if len(i1.getbands()) == 1:
# for gray-scale jpegs
dif = sum(abs(p1-p2) for p1,p2 in pairs)
else:
dif = sum(abs(c1-c2) for p1,p2 in pairs for c1,c2 in zip(p1,p2))
ncomponents = i1.size[0] * i1.size[1] * 3
diff = (dif / 255.0 * 100) / ncomponents
return diff
def main():
#capture_img = "/Users/Me/home1.png"
capture_img = input('enter path of the file from database')
#img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg"
take_and_save_picture(capture_img)
diff = compute_edges_diff(im1, im2)
print "Difference (percentage):", diff
if diff > 0.5:
print im1
else :
print im2
if __name__ == '__main__':
main()
#del(cap)
this code works fine .. but i am able to compare only one image ... i need to compare the current taken images with all images in my database ...
In your main function, create a list to ask for the path for the image files, wrap the compare in a for loop:
def get_images_to_compare():
images_to_compare = []
while True:
comp_img = raw_input("Path of image to compare to: ")
if len(comp_img) <= 1:
# break if someone just hits enter
break
images_to_compare.append(comp_img)
return images_to_compare
def main():
#capture_img = "/Users/Me/home1.png"
capture_img = input('enter path of the file from database')
#img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg"
take_and_save_picture(capture_img)
#### you have some odd var names here, basic gist, add a for loop
for comp_image in get_images_to_compare():
diff = compute_edges_diff(im1, im2)
print "Difference (percentage):", diff
if diff > 0.5:
print im1
else:
print im2
as a suggestion, avoid having global scope vars intermingled between functions, it makes code hard to read (referring to you setting im1 and im2 between two fn defs.
Code for doing the multiple compares:
def main(folder_path_to_search, files_to_compare_to, source_image_path):
#capture_img = "/Users/Me/home1.png"
capture_img = input('enter path of the file from database')
#img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg"
take_and_save_picture(capture_img)
images_to_compare = [ os.path.join(folder_path_to_search,file_path) for file_path in os.listdir(folder_path_to_search) if file_path.endswith(files_to_compare_to) ]
for comp_image in get_images_to_compare():
diff = compute_edges_diff(source_image_path, comp_image)
print "Difference (percentage):", diff, "(", source_image_path, ":", comp_image, ")"
if __name__ == '__main__':
folder_path_to_search = raw_input("Enter folder path to search")
files_to_compare_to = raw_input("enter file extention to glob ex: '.jpg'")
source_image_path = raw_input("enter full file path of source image")
main(folder_path_to_search, files_to_compare_to, source_image_path)

Categories

Resources