Thursday, June 09, 2016

Simple tools for simple tasks (an appreciation for....)

Maybe because I am fairly simple minded, I have always had a deep appreciation for "The Unix Philosophy" which to my thinking involves the idea that if you just need to solve a simple little problem quickly you just throw together a simple little tool to do it but at the same time make sure that there is a way to chain these little tools together in a way that can make the aggregate a truly useful and maybe powerful solution. The integration of this idea into the programs I interact with minute by minute all day every day (and the fact that the first versions were on Unix) make Mike Kitaif one of my heroes.  Yes almost every function, option, toolset has an easy, GUI, comprehensive way of dealing with it but at the same time almost all have a simple command equivalent with arguments that can be built upon using function keys, macros, or incredibly the python interpreter. When you combine this with the fact that rather than a monolithic database for hanging on to all the settings they are usually stored in tiny easily accessible (sometimes even text) files you get the opportunity to make the system do almost anything you can dream.

A great example of all this came up recently when I realized that under certain conditions I wanted to under certain conditions be able to view a particular vertical slice of LiDAR data and set the coloring based on elevation sub-slices.  There is of course a way to do this using the GUI for the poidis command.

There are also fairly straightforward ways to set all these things from the command line.
http://www.vrmapping.net/help5/index.html?point_display.htm

However, what I really wanted was the ability to input a minimal amount of information (base elevation and total slice thickness) and then have it display exactly what I wanted with the colors set to the sub slices (thickness divided by total number of available slices, or 20 currently) and here is where the python comes in. Granted the programming is about at the level of an 8 year old with a Raspberry Pi but you get the idea.

print 'viewsl.py modified 6:06 AM 5/6/2016'
# Views a slice of lidar with color by slice elevation.
'''
Copyright 2016 Dennis Shimer
Vr Mapping copyright Cardinal Systems, LLC
No warranties as to safety or usability expressed or implied.
Free to use, copy, modify, distribute with author credit.

A little more user friendly option to the Vr alternative which uses an
external parameter file which can be referenced by other programs
like bumvsl

'''
import os
import man
Ws=PyVrWs()
WsNum=Ws.Aws()
Gui=PyVrGui()

MinZ = Ws.GetMinMax (WsNum)[2]
MaxZ = Ws.GetMinMax (WsNum)[5]
AverageZ = (MaxZ+MinZ)/2.0

#In case the parameter file was never created before or can't be read for some reason
BaseZ=AverageZ
DelZMin=MinZ-AverageZ
DelZMax=MaxZ-AverageZ
Thickness=MaxZ-MinZ

ParFileName=VrCfg().GetVrHomeDir()+'/hostdir/viewslice.par'
if not os.path.isfile(ParFileName):
     open(ParFileName,'w').write('{:.2f} {:.2f} {:.2f} {:.2f}'.format(BaseZ,DelZMin,DelZMax,Thickness))
elif not os.path.getsize(ParFileName):
     open(ParFileName,'w').write('{:.2f} {:.2f} {:.2f} {:.2f}'.format(BaseZ,DelZMin,DelZMax,Thickness))
Params=open(ParFileName,'r').read().split()
BaseZ=float(Params[0])
Thickness=float(Params[3])

#In case the user passes in the numbers from the command line.
if VrArgs:
      BaseZ=float(VrArgs[0])
      Thickness=float(VrArgs[1])

PromBox = VrPromBox ("Set Z Slice", 30, 1)
PromBox.SetFocus()
PromBox.AddDouble('BaseZ',BaseZ,2)
PromBox.AddDouble('Thickness',Thickness,2)

if not VrArgs:
      if PromBox.Display(1)==0:
          BaseZ=PromBox.GetDoubleByPrompt('BaseZ')
          Thickness=PromBox.GetDoubleByPrompt('Thickness')
open(ParFileName,'w').write('{:.2f} {:.2f} {:.2f} {:.2f}'.format(BaseZ,DelZMin,DelZMax,Thickness))

#Just use the numbers to pass along arguments to the built in commands.
print BaseZ,DelZMin,DelZMax,Thickness
Gui.PushKeyin ('PoiFilZsl  On')
Gui.PushKeyin ('PoiFilZsl  BasZ {:.2f}'.format(BaseZ))
Gui.PushKeyin ('PoiFilZsl  MinDel {:.2f}'.format(0))
Gui.PushKeyin ('PoiFilZsl  MaxDel {:.2f}'.format(Thickness))

NumberOfSlices=20
SliceThickness = Thickness*1.08/NumberOfSlices #1.08 because it minimizes the top white slice.
print MinZ,MaxZ,SliceThickness,NumberOfSlices
Gui.PushKeyin ('PoiColSli  On')
Gui.PushKeyin ('PoiColSli  ResZ')
Gui.PushKeyin ('PoiColSli SliZ {:d} {:.2f} {:.2f}'.format(1,0,BaseZ))
CurrentElevation=BaseZ
for CurrentSliceNumber in range(2,NumberOfSlices):
    Gui.PushKeyin ('PoiColSli SliZ {:d} {:.2f} {:.2f}'.format(CurrentSliceNumber,CurrentElevation,CurrentElevation+SliceThickness))
    CurrentElevation+=SliceThickness
Gui.PushKeyin ('PoiColSli SliZ {:d} {:.2f} {:.2f}'.format(NumberOfSlices,CurrentElevation,1000000))

PyVrGr().Replot()

*Read the Wikipedia article if for no other reason than to better appreciate some of the men who helped make this all possible.

For anyone interested in trying VrPython for the first time or if you are early in the game, I suggest going to the earliest posts and working forward. I use VrPython every day for many wonderful things, needless to say it will change and could potentially damage a file. Any risk associated with using VrPython or any code or scripts mentioned here lies solely with the end user.

The "Personal VrPython page" in the link section will contain many code examples and an organized table of contents to this blog in a fairly un-attractive (for now) form.