Package: ddr-davis-data
ddr_davis_dataPakcage uses lvreader(1.2.0) to read and write .set file of Davis. lvreader is not installed with the package and hence it has to be installed separately. lvreader is not available on pypi (as of Sept 2022).Download and install lvreaderDownload.zipfile of lvreader(1.2.0) from hereExtract the.zipfile. lvreader has good manual to understand its usage. For independent use of lvreader, user can follow the manual. We will install the lvreader in our sytem from the.whl(wheel) files.
Inside there are multiple.whlfiles. According to the python version, the resective file needs to be installed. for Python 3.9.0 installlvreader-1.2.0-cp39-cp39-win_amd64.whl. For Python 3.10 installlvreader-1.2.0-cp310-cp310-win_amd64.whl.Above instructions assumes Windows as OS. For Linux the.whlfile name changes which is easily distinguishable in the list of files.Then open Anaconda powershell or cmd.exe. navigate to the extracted folder and perform the installation using pip.pipinstalllvreader-1.2.0-cp310-cp310-win_amd64.whlSelect the file name according to the Python version or-else the error will come.We have installed lvreader and all its required dependecies in the system. Now we will install ddr_davis_dataInstall ddr_davis_dataInstall ddr_davis_data using pip.pipinstallddr_davis_dataInstantiationimportddr_davis_dataimportmatplotlib.pyplotaspltimportnumpyasnpimportosprint(ddr_davis_data.version)0.1.19We need the filepath to Davis set. Here, we will take one average velocity set file. In Davis the files are arranges in chronological manner. The base or the first set (folder containing files) is of recorded images. Then folder inside the base set can be anything depending upon the processing performed. If background image is subtracted then, the next folder would contain subtracted images. Then next folder inside that folder would be instantaneous and then average velocity folder. The hierarchy of the folder depends upon the processing sequence performed. For the case shown here, the hierarchy is as follows.recorded images
│   .im7 files - all images (from 0 to 100 or 1000)
│   ...
|   background subtracted images.set
└───background subtracted images
    │   .im7 files
    │   ...
    |   instantaneous velocity fields.set
    └───instantaneous velocity fields
        │   .vc7 files containing Vx, Vy or Vz (depending upon type of PIV)
        │   ...
        |   average velocity field.set
        └───average velocity field
            │   .vc7 files containing average of Vx, Vy or Vz (depending upon type of PIV)
            │   ... another files depending upon the processingIn this case, we will take instantaneous set file. The set file is located in the parent directory of the folder as shown above. For the filepath, we can either give the path to.setfile or folder path.filepath1=r'D:\recorded images\background subtracted images\instantaneous velocity fields's1=ddr_davis_data.velocity_set(filepath=filepath1,load=True,rec_path=None,load_rec=False)s1 is the velocity set object. If the set folder is in hierarchy of the recorded image, then load_rec=True will load the recording set as well. Loading recording set helps in accessing recoded or raw images. To make the instantiation of velocity_set faster with recording set, it is better to give recoding set folder-path directly to rec_path attribute above.Accessing dataEvery set file has many of attributes such asscales, offsets, limits, U0, V0, camera exposure time, Laser power, recording time, recording rate etc..s1.attributesThis will give the dictionary-like data of all the attributes attached with the s1 set file.
There are default and intuitive functions to get certain important attributes as follows.len(s1)100This gives the number of images in the velocity set.s1.recording_rate10.0gives the recording rate of the s1 set file. similary the time delta in between the frames can be accesssed by,s1.dt49.0Depending upon the way Davis packs the data, sometimes the attribute name changes and then the above functions might not work. At that time it is better to access data usings1.attributesVelocity dataVelocity data can be accessed by giving comonent name. Method returns the numpy_masked_array like data.s1.u(n=0)masked_array(
  data=[[--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --],
        ...,
        [--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --]],
  mask=[[ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True],
        ...,
        [ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True]],
  fill_value=0.0)This is the $V_x$ velocity with masks. Mask crops the useful data from the overall image. During velocity calculation in Davis if Mask is enabled (geometric mask) then the output velocities will have mask accordingly. Mostly PIV frames are not 100% used for velocity measurements. Meaning if jet is flowing from center of the image then the corners of the image is rendered useless for velocity measurement. Masks helps in neglecting those areas. It only considers the area of interest.Similarly $V_y$ can be accessed as follows.s1.v(n=21)masked_array(
  data=[[--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --],
        ...,
        [--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --],
        [--, --, --, ..., --, --, --]],
  mask=[[ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True],
        ...,
        [ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True],
        [ True,  True,  True, ...,  True,  True,  True]],
  fill_value=0.0)n is the image number for which velocity is enquired. If there are 100 images then n ranges from 0 to 99. As s1 is instantaneous set file, it contains many.vc7files. But for average set file, there will be only one .vc7 file which will have average of velocity components, then n should be 0 (which is its default value).s1.vector_coords(n=0)x= [[-1.         -0.99659864 -0.99319728 ... -0.00680272 -0.00340136
   0.        ]
 [-1.         -0.99659864 -0.99319728 ... -0.00680272 -0.00340136
   0.        ]
 [-1.         -0.99659864 -0.99319728 ... -0.00680272 -0.00340136
   0.        ]
 ...
 [-1.         -0.99659864 -0.99319728 ... -0.00680272 -0.00340136
   0.        ]
 [-1.         -0.99659864 -0.99319728 ... -0.00680272 -0.00340136
   0.        ]
 [-1.         -0.99659864 -0.99319728 ... -0.00680272 -0.00340136
   0.        ]]
y= [[ 0.          0.          0.         ...  0.          0.
   0.        ]
 [-0.00452489 -0.00452489 -0.00452489 ... -0.00452489 -0.00452489
  -0.00452489]
 [-0.00904977 -0.00904977 -0.00904977 ... -0.00904977 -0.00904977
  -0.00904977]
 ...
 [-0.99095023 -0.99095023 -0.99095023 ... -0.99095023 -0.99095023
  -0.99095023]
 [-0.99547511 -0.99547511 -0.99547511 ... -0.99547511 -0.99547511
  -0.99547511]
 [-1.         -1.         -1.         ... -1.         -1.
  -1.        ]]Returns tuples of numpy-array like data. The data is mesh-grid of $X$ and $Y$ coordinates of velocity vectors.PlottingContour, Streamline, Quiver etc. plots can be made from the meshgrid coordinate data and velocity vector data which we accessed above. There are special methods which is described below to output the data for plots and also there are plotting functions in the library to directly plot the data.s1.plot(n=10)Above code directly access thelvreader.frame.VectorFrame.plot()function. There are separate functions in the module to plot various informations.Plot filled contourddr_davis_data.plot_contourf(*args,**kwargs)is used to plot filled contour. There are 2 ways to use the function.1) Giving velocity_set as inputfig=plt.figure(figsize=(3,1.5))ax=fig.add_subplot(111)ddr_davis_data.plot_contourf(ax=ax,vel_set=s1,n=10,z='velocity_magnitude',font_size=7,ctitle='|V|',clabel='[m/s]',labelpad=10)plt.show()nis the image/frame number.zdetermines which scalar to plot. There are many options to that depending upon the Davis output file. Currently 'u,v,velocity_magnitude, omega_z, Wz, TKE' options are available. There is a workaround this method of plotting which we will see shortly. Other attributes can be understood from its name or from plot outcome.Multiple axesaxis the axes on which to plot the contour. If there are multiple subplots then this attribute is very helpful. Below code plots the $V_x$ and $V_y$ in two different subplots.fig=plt.figure(figsize=(8,2))ax1=fig.add_subplot(121)ddr_davis_data.plot_contourf(ax=ax1,vel_set=s1,n=7,z='u',font_size=10,ctitle='$V_x$',clabel='[m/s]',labelpad=10)ax2=fig.add_subplot(122)ddr_davis_data.plot_contourf(ax=ax2,vel_set=s1,n=7,z='v',font_size=10,ctitle='$V_y$',clabel='[m/s]',labelpad=10)plt.show()2) Giving data as inputThis method of plotting gives better control over the data to be plotted. In the previous example, we gave velocity_set as input. The plotting function makes the data inside usingzvalue. If we make the data outside the function and give the data to plotting function then it will do the same thing, but we could do multiple mathematical manipulation of data before plotting.datashould be dictionary like object.d1=s1.make_data(n=10)Gives the dict output with 'x','y','u' and 'v' keys with numpy_masked array like values. To make the data ready for plottingd1['z']should be set to the scalar which we want to plot.fig=plt.figure(figsize=(8,2))d1=s1.make_data(n=10)ax1=fig.add_subplot(121)d1['z']=d1['u']ddr_davis_data.plot_contourf(ax=ax1,data=d1,font_size=7,ctitle='$V_x$ [m/s]')ax2=fig.add_subplot(122)d1['z']=d1['v']ddr_davis_data.plot_contourf(ax=ax2,data=d1,font_size=7,ctitle='$V_y$ [m/s]')plt.show()This will plot the same figure as plotted previously using velocity_set. Now here we could do mathematical manipulation of data before storing it tod1['z']. If bothvel_setanddataare defined thendatais given the priority abovevel_set.Common colorbar and use ofvmaxandvminvmaxandvmincomes handy when we want to plot common colorbar for multiple subfigures. below code shows the example for the same.vmin=-1vmax=0colormap='hot'fig=plt.figure(figsize=(5,1.5))d1=s1.make_data(n=10)ax1=fig.add_subplot(121)d1['z']=d1['u']ddr_davis_data.plot_contourf(ax=ax1,data=d1,vmax=vmax,vmin=vmin,add_colorbar=False,colormap=colormap)ax2=fig.add_subplot(122)d1['z']=d1['v']ddr_davis_data.plot_contourf(ax=ax2,data=d1,vmax=vmax,vmin=vmin,add_colorbar=False,colormap=colormap)plt.tight_layout()#adding colorbar to the rightplt.subplots_adjust(right=0.85)ax=fig.add_axes([0.92,0.05,0.015,0.85])ddr_davis_data.plot_colorbar(vmin=vmin,vmax=vmax,cax=ax,font_size=7,colormap=colormap,roundto=2,ctitle='$Common$ [m/s]')plt.show()In the above plots we have changed the type ofcolormaptohot.Plot quiver (vectors)The method to plot the quiver is almost same as above. It shares the same code architechture. There is difference infracxandfracyattributes, which controlls the amount of vectors displayed in $X$ and $Y$ axes respectively. The higher the number, less the amount of vectors displayed.Vectors makes more sense when displayed over the contour plot. Hence below figure will plot vectors over the contour plot.fig=plt.figure(figsize=(3,1.5))ax1=fig.add_subplot(111)d1=s1.make_data(n=10)#calculating velocity_magnituded1['z']=(d1['u']**2+d1['v']**2)**0.5#plotting contour of velocity magnitudeddr_davis_data.plot_contourf(ax=ax1,data=d1,font_size=7,ctitle='|V| [m/s]')#plotting vectors, here the width and scale are adjusted for better visionddr_davis_data.plot_quiver(ax=ax1,data=d1,fracx=5,fracy=5,scale=20,width=0.007,color='#000000ff',normalize=True)plt.show()normalize = Trueattribute will normalize the velocity values. This helps when the velocity magnitudes changes very much within the plot.Plot streamlinesWhen data froms1.make_data()is supplied tomatplotlib.pyplot.streamplot()then error ofstrictly increasing arraypops up. Hence turnaround was to use 1D linear array. There is special function within the velocity_set object which gives the data to plot for streamlines.fig=plt.figure(figsize=(3,1.5))ax1=fig.add_subplot(111)d1=s1.make_data(n=10)d1['z']=(d1['u']**2+d1['v']**2)**0.5ddr_davis_data.plot_contourf(ax=ax1,data=d1,font_size=7,ctitle='|V| [m/s]')d1=s1.make_streamline_data(n=10)ddr_davis_data.plot_streamlines(ax=ax1,data=d1,density=(5,5),linewidth=1,color='white',arrowsize=0.01)plt.show()herearrowsizeis 0.01 for better visualization. But for some cases, defaultarrowsizegives good results.get $\omega_z$There is a function to calculate $\omega_z$ from the data. The function accepts the data in dict like object form.d1=s1.make_data(n=0)d1=get_omega_z(data=d1)d1['z']contains the calculated $\omega_z$ from the given data. You can further use this dict like data in plotting or any analysis.Similarly there is functionget_mod_Vwhich accepts the same dict like data, and calculates the velocity magnitude. As this calculation is one line and you can do it easily, the usage of function is not specifically described here.Accessing recording imagesRecording images can be accessed ifload_rec=Truein instantiation of velocity_set object. Also there should be recording.setfiles in the parent directory (at any level) of the velocity set file.s1=ddr_davis_data.velocity_set(filepath=filepath1,load=True,rec_path=None,load_rec=True)plotting the imageThe structure to plot image is similar to contour plot.make the datad1 = s1.make_image_data(n=10)plot the dataddr_davis_data.plot_image(data=d1)fig=plt.figure(figsize=(3,1.5))ax1=fig.add_subplot(111)d1=s1.make_image_data(n=10,frame=0)ddr_davis_data.plot_image(ax=ax1,data=d1,vmin=0,vmax=60)plt.show()Rotate basesDavis considers the $V_x$ in horizontal direction and $V_y$ in vertical direction. But for some cases, the physical bases (coordinate system) can be different. Say, $45^{\circ}$. Then we need to project our vectors in that perticular bases.rotate_bases()function does the work for us. Rotation angle must be in degrees.vmin=-1vmax=1colormap='cool'fig=plt.figure(figsize=(5,1.5))ax1=fig.add_subplot(121)d1=s1.make_data(n=25)d1['z']=d1['u']ddr_davis_data.plot_contourf(ax=ax1,data=d1,vmax=vmax,vmin=vmin,add_colorbar=False,colormap=colormap)ax1.set_title('original bases')ax2=fig.add_subplot(122)# this function rotates the basesd1=ddr_davis_data.rotate_bases(d1,angle=45)ddr_davis_data.plot_contourf(ax=ax2,data=d1,vmax=vmax,vmin=vmin,add_colorbar=False,colormap=colormap)ax2.set_title('rotated bases')plt.tight_layout()plt.subplots_adjust(right=0.85)ax=fig.add_axes([0.92,0.05,0.015,0.85])ddr_davis_data.plot_colorbar(vmin=vmin,vmax=vmax,cax=ax,font_size=7,colormap=colormap,roundto=2,ctitle='$V_x$ [m/s]',cticks=5)plt.show()rotate_bases()function returns the same dict like data type with $V_x$ and $V_y$ projected on rotated bases. here X and Y axis are not rotated.  Only the velocities are represented in new bases. So, now in new $V_x$ the x axis is aligned at $45^{\circ}$ from the horizontal.note that the axis are not rotated. Here the velocity and any point (x,y) is projected on new bases but the velocity vector is still of point (x,y).Rotate Coordinate axisTo rotate the coordinate system we can use therotate_coordinates_degrees()function. Here input angle must be in degrees.vmin=-1vmax=1colormap='cool'fig=plt.figure(figsize=(5,1.5))ax1=fig.add_subplot(121)d1=s1.make_data(n=25)d1['z']=d1['u']ddr_davis_data.plot_contourf(ax=ax1,data=d1,vmax=vmax,vmin=vmin,add_colorbar=False,colormap=colormap)ax2=fig.add_subplot(122)d1['x'],d1['y']=ddr_davis_data.rotate_coordinates_degrees(d1['x'],d1['y'],angle=45)ddr_davis_data.plot_contourf(ax=ax2,data=d1,vmax=vmax,vmin=vmin,add_colorbar=False,colormap=colormap)plt.tight_layout()plt.subplots_adjust(right=0.85)ax=fig.add_axes([0.92,0.05,0.015,0.85])ddr_davis_data.plot_colorbar(vmin=vmin,vmax=vmax,cax=ax,font_size=7,colormap=colormap,roundto=2,ctitle='$V_x$ [m/s]',cticks=5)plt.show()Get data at a pointget_data_at_point()function gives thezvalue at(px,py)point from the domain.d1=s1.make_data(n=25)d1['z']=d1['u']print(ddr_davis_data.get_data_at_point(data=d1,px=20,py=50))-1.3974445965482185Get data at (on) the lineget_data_at_line()function returns the x,y,z values. where x,y are points on the line and z is the scalar at al (x,y) points.d1=s1.make_data(n=25)d1['z']=d1['u']# getting data over the linex,y,z=ddr_davis_data.get_data_at_line(data=d1,x1=-30,y1=20,x2=40,y2=50,n_points=100)fig=plt.figure(figsize=(5,1.5))ax1=fig.add_subplot(121)# plotting contour plotddr_davis_data.plot_contourf(data=d1,vmax=1,vmin=-1,ax=ax1,font_size=5,colormap='cool')#plotting line over the contour plotax1.scatter(x,y,s=1,c='k')ax2=fig.add_subplot(122)# plotting z values w.r.t yax2.scatter(y,z/z.max(),s=1,c='k')plt.tight_layout()plt.show()Saving the data to other directory in .npy formatWe need to give the name to the set and the folder path where the set will be stored. The function stores the X, Y coordinates and stores the U and V velocities image wise in subfolder.set_foldpath=r'D:'set_name='set1'ddr_davis_data.save_set(s1,set_name=set_name,set_foldpath=set_foldpath,n_start=0,n_end=3,print_info=True)saving velocities
0
1
2n_startandn_endspecifies the starting and ending velocity files to be stored.print_info = Falsewill disable the output shown aboveWorking with local dataWe can give the path to above local set, and perform all the operation with velocity datas. As we have not saved any attributes we could not retrieve it with local data.# loading local setls1=ddr_davis_data.local_set(set_name=set_name,set_foldpath=set_foldpath)fig=plt.figure(figsize=(3,1.5))#plotting the contour plotd1=ls1.make_data(n=2)d1['z']=d1['u']ddr_davis_data.plot_contourf(data=d1,vmax=1,vmin=-1,colormap='cool',font_size=5)plt.show()we can get the length of the local set as followsprint(len(ls1))3Handling multiple velocitites framesmultiple velocities frames can be combined togather in single 3-D array. That array can be saved and retried later. We call this kind of multiple frames asUsandVs.# make 3-D arrayprint(ls1.get_multiple_u(0,3).shape)(222, 295, 3)Save theUsandVs.ls1.save_UVs(n_start=0,n_end=-1)Load theUsprint(ls1.Vs.shape)(222, 295, 3)