I am working on creating a python toolbox to solve for WiFi signal properties based on various inputs, and for the end result I would like to have the output in the form of a raster. I need this raster to take on an equation value (FSPL) for each cell, based on a cost raster (distance raster) and numerical inputs (frequency type in GHz and feet-meter conversion coefficient). Below is the code that I have attempted, but I get an error reading:
Traceback (most recent call last):
File "<string>", line 108, in execute
TypeError: can't multiply sequence by non-int of type 'float'.
Failed to execute (FSPL).
Here is the code below (with line 108 marked with writing in the code itself near the bottom):
import arcpy
import math
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Toolbox Label Property"
self.alias = "Toolbox Alias Property"
# List of tool classes associated with this toolbox
self.tools = [FSPL, WAP_Buffer]
class FSPL(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "Free Space Path Loss"
self.description = "This python script tool will create Free Space Path Loss to determine the dB range output from the WAPs."
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
param0 = arcpy.Parameter(
displayName="Wireless Access Points",
name="wireless_pts",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
param1 = arcpy.Parameter(
displayName="Network Frequency Type",
name="network_freq",
datatype="String",
parameterType="Required",
direction="Input")
param1.filter.type="ValueList"
param1.filter.list = ["2.4 GHz", "5 GHz"]
param2 = arcpy.Parameter(
displayName="Distance Raster",
name="dist_rast",
datatype="GPRasterLayer",
parameterType="Required",
direction="Input")
param3 = arcpy.Parameter(
displayName="Distance Raster Units",
name="units",
datatype="String",
parameterType="Required",
direction="Input")
param3.filter.type="ValueList"
param3.filter.list = ["Feet", "Meters"]
param4 = arcpy.Parameter(
displayName="Output Raster",
name="output_rast",
datatype="GPRasterLayer",
parameterType="Required",
direction="Output")
return [param0, param1, param2, param3, param4]
def isLicensed(self):
"""Set whether tool is licensed to execute."""
return True
def updateParameters(self, parameters):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
return
def updateMessages(self, parameters):
"""Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation."""
return
def execute(self, parameters, messages):
"""The source code of the tool."""
#Get inputs
wireless_pts = parameters[0].valueAsText
network_freq = parameters[1].valueAsText
dist_rast = parameters[2].valueAsText
units = parameters[3].valueAsText
output_rast = parameters[4].valueAsText
shapeFieldName = arcpy.Describe(wireless_pts).shapeFieldName
#Create expression
if network_freq == "2.4 GHz":
hertz=2400000000
else:
hertz=5000000000
if units == "Feet":
distmod=0.3048
else:
distmod=1
#equation
LINE 108 fspl= (4 * math.pi * distmod * dist_rast * hertz)/(2.99792458 * (10**8))
output_rast = fspl
return
I am fairly new to using python and there could be something very basic that I am not grasping. This all seemed a little to easy for someone without much python experience to produce, and so I am skeptical that I am forgetting something big. If anyone has any ideas on how I can implement what I want to produce I would be very happy to hear them.
I think your problem lies in this line:
dist_rast = parameters[2].valueAsText
If it's doing what I think it is it's returning a string object that can't be multiplied by a float (which you're trying to do with math.pi, possibly distmod)
Instead, convert this to a float as well and try again.
Related
I've been trying to create a TrajectorySource for RigidTransforms to pass into a DifferentialInverseKinematicsIntegrator which only takes in RigidTransforms in its input port.
def createTraj(time, pose):
times = []
poses = []
for step in time:
times.append(time[step])
poses.append(pose[step])
return PiecewisePose.MakeLinear(times, poses)
Initially, I tried to directly pass in the output from createTraj above into TrajectorySource but ran into the issue of my trajectory having more than one columns: Failure at systems/primitives/trajectory_source.cc:21 in TrajectorySource(): condition 'trajectory.cols() == 1' failed.
import matplotlib.pyplot as plt, mpld3
class DexterTest():
# Output from createTraj is passed as parameter: traj into constructor
def __init__(self, traj):
builder = DiagramBuilder()
self.station = DexterPPStation(1e-4, "/opt/drake/share/drake/manipulation/models/final_dexter_description/urdf/dexter.urdf")
self.station.CreateBins("/opt/drake/share/drake/examples/manipulation_station/models/bin.sdf", RigidTransform(np.array([0.5,0,0])), RigidTransform(np.array([0,0.5,0])))
self.station.CreateRandomPickingObjects(3)
self.station.AddDexter()
builder.AddSystem(self.station)
self.station.Finalize()
self.diff_ik = DifferentialInverseKinematicsIntegrator(self.station.controller_plant, self.station.plant.GetFrameByName("link6", self.station.dexter["instance"]), self.station.time_step, DifferentialInverseKinematicsParameters(7,7))
builder.AddSystem(self.diff_ik)
#=========================================== Likely Source of Error ===========================================
pose = builder.AddSystem(PoseSystem())
p_G_source = builder.AddSystem(TrajectorySource(traj.get_position_trajectory()))
w_G_source = builder.AddSystem(TrajectorySource(traj.get_orientation_trajectory()))
builder.Connect(p_G_source.get_output_port(), pose.GetInputPort("p_G"))
builder.Connect(w_G_source.get_output_port(), pose.GetInputPort("r_G"))
builder.Connect(pose.get_output_port(), self.diff_ik.get_input_port())
#======================================================================================
MeshcatVisualizerCpp.AddToBuilder(builder, self.station.GetOutputPort("query_object"), meshcat)
self.diagram = builder.Build()
self.simulator = Simulator(self.diagram)
self.diagram_context = self.simulator.get_mutable_context()
self.station_context = self.station.GetMyMutableContextFromRoot(self.diagram_context)
self.plant_context = self.station.GetSubsystemContext(self.station.plant, self.station_context)
self.station.SetRandomPoses(self.plant_context)
builder.Connect(self.diff_ik.get_output_port(), self.station.GetInputPort("dexter_position"))
def run(self):
self.simulator.set_target_realtime_rate(2.0)
self.simulator.AdvanceTo(1)
class PoseSystem(LeafSystem):
def __init__(self):
LeafSystem.__init__(self)
self.p_G = self.DeclareVectorInputPort("p_G", BasicVector(3))
self.r_G = self.DeclareVectorInputPort("r_G", BasicVector(4))
self.DeclareAbstractOutputPort("X_G", Value[RigidTransform], self.CalcOutput)
def CalcOutput(self, context, output):
pose = RigidTransform(Quaternion(self.r_G.Eval(context)), self.p_G.Eval(context))
output.set_value(pose)
Instead, I tried to break up my trajectory into its orientation and position parts, add them to the input ports of a custom system, and then reconstruct them together in the output port. However, this gives me the following RuntimeError once the run method is called: RuntimeError: This multibody element does not belong to the supplied MultibodyTree.
Any help would be greatly appreciated!
I think you are very close. The PoseSystem looks like it should be a solution to the problem you've articulated in your post. (The error about MultibodyTree must be coming from the other part of your code.
You don't actually need to break the RigidTransform up into orientation / translation to create your PoseSystem, your CalcOutput could just call output.set_value(poses.Eval(t)) if poses is a PiecewisePose trajectory.
I have an example of doing this in the PickAndPlaceTrajectory class in this notebook: https://github.com/RussTedrake/manipulation/blob/008cec6343dd39063705287e6664a3fee71a43b8/pose.ipynb
I'm trying to put some functioning code into a python toolbox in arcgis (Python 2.7).
I've run the code externally using arcpy.
I've setup a new python toolbox, edited a single parameter, a string with a site code e.g. SiteX.
This should set the default online_id to "SiteX" and the SiteCode to "SiteX20".
The messages list all the feature classes but it is not liking arcpy.AssignDefaultToField_management():
class Tool(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "Tool"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
param0 = arcpy.Parameter(
displayName="Site Code",
name="online_id",
# datatype="Field",
datatype="GPString",
# parameterType="Optional",
parameterType="Required",
direction="Input")
params = [param0]
# params = None
return params
def isLicensed(self):
"""Set whether tool is licensed to execute."""
return True
def updateParameters(self, parameters):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
return
def updateMessages(self, parameters):
"""Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation."""
return
def execute(self, parameters, messages):
online_id = parameters # user request required
# online_id = arcpy.GetParameterAsText(online_id)
# online_id = raw_input('Enter your value :')
dateyr = time.strftime("%y", time.localtime())
sitecode = str(online_id) + str(dateyr)
arcpy.env.workspace = arcpy.env.workspace + "\\survey"
fclist = arcpy.ListFeatureClasses()
arcpy.AddMessage(arcpy.env.workspace)
arcpy.AddMessage(online_id)
arcpy.AddMessage(sitecode)
# Loop through all the feature classes and assign the default value for online_id
for fc in fclist:
arcpy.AddMessage(fc)
arcpy.AddMessage("{0} has {1} features.".format(fc, online_id))
arcpy.AssignDefaultToField_management(in_table=fc, field_name="online_id", default_value=online_id)
# arcpy.AssignDefaultToField_management(in_table=fc, field_name="site_code", default_value=sitecode)
return
Edit
The error message given by arcgis:
Executing: Tool X
Start Time: Tue Oct 06 15:57:33 2020
Running script Tool...
S:\PROJECTS\Workflow\GN_Coding\OA\03 GIS Projects - Coding Review\Geodatabase\DRS_survey_data.gdb\survey
[<geoprocessing parameter object object at 0x50DF5FC0>]
[<geoprocessing parameter object object at 0x50DF5FC0>]20
drafting_ply
drafting_ply has [<geoprocessing parameter object object at 0x50DF5FC0>] features.
Traceback (most recent call last):
File "<string>", line 75, in execute
File "c:\program files (x86)\arcgis\desktop10.5\arcpy\arcpy\management.py", line 3574, in AssignDefaultToField
raise e
RuntimeError: Object: Error in executing tool
Failed to execute (Tool).
Failed at Tue Oct 06 15:57:40 2020 (Elapsed Time: 7.53 seconds)
You should set online_id = parameters[0].value. This should give you online_id set to a string since your parameter is a string type.
I'm trying to get into Extension programming in 3DSlicer using Python.
There is a tutorial online. Unfortunately there is a problem with the third example script "HelloSharpen". I did the exact same thing they did but I get this error:
Traceback (most recent call last):
File "C:/Users/johan/Desktop/HelloPythonSlicer4/helloPython/code/HelloSharpen.py", line 105, in onApply
laplacian.SetInput(inputVolume.GetImageData())
AttributeError: 'vtkImagingGeneralPython.vtkImageLaplacian' object has no attribute 'SetInput'
I solved this by changing laplacian.SetInput(inputVolume.GetImageData()) to laplacian.SetInputData(inputVolume.GetImageData()) because I read that they changed this in the newer versions of VTK.
However when I try to run this a new error comes up:
Traceback (most recent call last):
File "C:/Users/johan/Desktop/HelloPythonSlicer4/helloPython/code/HelloSharpen.py", line 107, in onApply
laplacian.GetOutput().Update()
AttributeError: 'vtkCommonDataModelPython.vtkImageData' object has no attribute 'Update'
It seems that laplacian.GetOutput().Update() is causing problems so
I tried to find something on the Internet if they also changed this in the newer versions of VTK but I couldn't find anything. I tried to change this into "UpdateData" but this doesn't work.
Do you know if they also changed this and if yes, do you know what I should replace this with?
Here is the full code for "HelloSharpen":
from __main__ import vtk, qt, ctk, slicer
#
# HelloSharpen
#
class HelloSharpen:
def __init__(self, parent):
parent.title = "Hello Python Part D - Sharpen"
parent.categories = ["Examples"]
parent.dependencies = []
parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",
"Steve Pieper (Isomics)",
"Sonia Pujol (BWH)"] # replace with "Firstname Lastname (Org)"
parent.helpText = """
Example of scripted loadable extension for the HelloSharpen tutorial.
"""
parent.acknowledgementText = """
This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
Steve Pieper, Isomics, Inc., and Sonia Pujol, Brigham and Women's Hospital and was
partially funded by NIH grant 3P41RR013218-12S1 (NAC) and is part of the National Alliance
for Medical Image Computing (NA-MIC), funded by the National Institutes of Health through the
NIH Roadmap for Medical Research, Grant U54 EB005149.""" # replace with organization, grant and thanks.
self.parent = parent
#
# qHelloPythonWidget
#
class HelloSharpenWidget:
def __init__(self, parent = None):
if not parent:
self.parent = slicer.qMRMLWidget()
self.parent.setLayout(qt.QVBoxLayout())
self.parent.setMRMLScene(slicer.mrmlScene)
else:
self.parent = parent
self.layout = self.parent.layout()
if not parent:
self.setup()
self.parent.show()
def setup(self):
# Collapsible button
self.laplaceCollapsibleButton = ctk.ctkCollapsibleButton()
self.laplaceCollapsibleButton.text = "Sharpen Operator"
self.layout.addWidget(self.laplaceCollapsibleButton)
# Layout within the laplace collapsible button
self.laplaceFormLayout = qt.QFormLayout(self.laplaceCollapsibleButton)
#
# the volume selectors
#
self.inputFrame = qt.QFrame(self.laplaceCollapsibleButton)
self.inputFrame.setLayout(qt.QHBoxLayout())
self.laplaceFormLayout.addWidget(self.inputFrame)
self.inputSelector = qt.QLabel("Input Volume: ", self.inputFrame)
self.inputFrame.layout().addWidget(self.inputSelector)
self.inputSelector = slicer.qMRMLNodeComboBox(self.inputFrame)
self.inputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
self.inputSelector.addEnabled = False
self.inputSelector.removeEnabled = False
self.inputSelector.setMRMLScene( slicer.mrmlScene )
self.inputFrame.layout().addWidget(self.inputSelector)
self.outputFrame = qt.QFrame(self.laplaceCollapsibleButton)
self.outputFrame.setLayout(qt.QHBoxLayout())
self.laplaceFormLayout.addWidget(self.outputFrame)
self.outputSelector = qt.QLabel("Output Volume: ", self.outputFrame)
self.outputFrame.layout().addWidget(self.outputSelector)
self.outputSelector = slicer.qMRMLNodeComboBox(self.outputFrame)
self.outputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
self.outputSelector.setMRMLScene( slicer.mrmlScene )
self.outputFrame.layout().addWidget(self.outputSelector)
self.sharpen = qt.QCheckBox("Sharpen", self.laplaceCollapsibleButton)
self.sharpen.toolTip = "When checked, subtract laplacian from input volume"
self.sharpen.checked = True
self.laplaceFormLayout.addWidget(self.sharpen)
# Apply button
laplaceButton = qt.QPushButton("Apply")
laplaceButton.toolTip = "Run the Laplace or Sharpen Operator."
self.laplaceFormLayout.addWidget(laplaceButton)
laplaceButton.connect('clicked(bool)', self.onApply)
# Add vertical spacer
self.layout.addStretch(1)
# Set local var as instance attribute
self.laplaceButton = laplaceButton
def onApply(self):
inputVolume = self.inputSelector.currentNode()
outputVolume = self.outputSelector.currentNode()
if not (inputVolume and outputVolume):
qt.QMessageBox.critical(
slicer.util.mainWindow(),
'Sharpen', 'Input and output volumes are required for Laplacian')
return
# run the filter
laplacian = vtk.vtkImageLaplacian()
laplacian.SetInputData(inputVolume.GetImageData())
laplacian.SetDimensionality(3)
laplacian.GetOutput().Update()
ijkToRAS = vtk.vtkMatrix4x4()
inputVolume.GetIJKToRASMatrix(ijkToRAS)
outputVolume.SetIJKToRASMatrix(ijkToRAS)
outputVolume.SetAndObserveImageData(laplacian.GetOutput())
# optionally subtract laplacian from original image
if self.sharpen.checked:
parameters = {}
parameters['inputVolume1'] = inputVolume.GetID()
parameters['inputVolume2'] = outputVolume.GetID()
parameters['outputVolume'] = outputVolume.GetID()
slicer.cli.run( slicer.modules.subtractscalarvolumes, None, parameters, wait_for_completion=True )
selectionNode = slicer.app.applicationLogic().GetSelectionNode()
selectionNode.SetReferenceActiveVolumeID(outputVolume.GetID())
slicer.app.applicationLogic().PropagateVolumeSelection(0)
TL;DR Change laplacian.GetOutput().Update() to laplacian.Update().
Explanation:
As per this link, there was a major change introduced in VTK 6. In summary, newer versions of VTK have separated algorithms and the data in two different class hierarchies. In newer versions of VTK, the Update() function can be called only on objects which have been derived from the vtkAlgorithm class. You can look at the inheritance diagram of vtkImageLaplacian here and it is indeed derived from vtkAlgorithm class. So laplacian.Update() will work.
As the name suggests vtkImageData is a data object. laplacian.GetOutput() returns a vtkImageData object and that's why you cannot call Update() function on it and therefore you get the error.
Im writing a custom reader node for maya (in python with openmaya API 2.0) and I would like to send my uv sets to a regular maya mesh node.
Im wondering what would be the best way to push the uv sets in a mesh node? I wasn't able to find what data I have to create and how to send them to the mesh node.
My reader is a OpenMaya.MPxNode who push custom data to a OpenMaya.MPxSurfaceShape. The shape is linked by out mesh / in mesh plugs to a regular maya mesh. I attempt to fill the uvSet plug of this shape using compute but without success. I expect the UVSets to be sent to the mesh.
The following code sample is a limited test where my only goal is to create a new UVSet and attach it to the mesh.
Any ideas or documentation which could help?
I tried several things but I always get the error below.
The error:
// Error: (kFailure): Object does not exist
# Traceback (most recent call last):
# File "/path/to/maya/plug-ins/test_create_uv_set.py", line 60, in compute
# mesh.createUVSet("toto")
# RuntimeError: (kFailure): Object does not exist //
The running code:
"""
usage
import maya.cmds as cmds
import pymel.core as pm
cmds.loadPlugin("/path/to/maya/plug-ins/test_create_uv_set.py")
transform_node = pm.polySphere(n='transform1', ch=1, o=1, r=4)[0]
mesh1_node = transform_node.getShape()
pm.setAttr(mesh1_node + ".visibility", False)
uv_set_mod_node = pm.createNode("uvSetModifier", name="uvsetmodifier1")
mesh2_node = pm.createNode("mesh", name="mesh2", parent=transform_node)
pm.hyperShade(assign="initialShadingGroup")
pm.Attribute.connect(mesh1_node.attr("outMesh"), uv_set_mod_node.attr("inMesh"))
pm.Attribute.connect(uv_set_mod_node.attr("outMesh"), mesh2_node.attr("inMesh"))
"""
import sys
import maya.api.OpenMaya as OpenMaya
def maya_useNewAPI():
pass
class uvSetModifier(OpenMaya.MPxNode):
typeName = "uvSetModifier"
id = OpenMaya.MTypeId(0xCCCCC)
inMesh = None
outMesh = None
#staticmethod
def creator():
return uvSetModifier()
#staticmethod
def initialize():
typedAttr = OpenMaya.MFnTypedAttribute()
uvSetModifier.inMesh = typedAttr.create("inMesh", "im", OpenMaya.MFnData.kMesh)
typedAttr.writable = True
OpenMaya.MPxNode.addAttribute(uvSetModifier.inMesh)
uvSetModifier.outMesh = typedAttr.create("outMesh", "om", OpenMaya.MFnData.kMesh)
typedAttr.writable = True
OpenMaya.MPxNode.addAttribute(uvSetModifier.outMesh)
def __init__(self):
OpenMaya.MPxNode.__init__(self)
def compute(self, plug, datablock):
if plug == uvSetModifier.outMesh:
inputData = datablock.inputValue(uvSetModifier.inMesh)
outputData = datablock.outputValue(uvSetModifier.outMesh)
outputData.setMObject(inputData.asMesh())
mesh = OpenMaya.MFnMesh(inputData.asMesh())
mesh.createUVSet("toto")
datablock.setClean(plug)
def initializePlugin(obj):
plugin = OpenMaya.MFnPlugin(obj, "Autodesk", "3.0", "Any")
try:
plugin.registerNode(uvSetModifier.typeName, uvSetModifier.id, uvSetModifier.creator, uvSetModifier.initialize)
except:
sys.stderr.write("Failed to register node\n")
raise
def uninitializePlugin(obj):
plugin = OpenMaya.MFnPlugin(obj)
try:
plugin.deregisterNode(uvSetModifier.id)
except:
sys.stderr.write("Failed to deregister node\n")
pass
UPDATE 1: THEODOX input
I added the following line (59)
if inputData.asMesh() is not None:
print "test"
mesh = OpenMaya.MFnMesh(inputData.asMesh())
mesh.createUVSet("toto")
results: I still get the same error message
I have two Scripts. Script 1 is titled schemeDetails.The second script is a test script called temporaryFile that creates a schemeSetup object using the schemeSetup class which is within schemeDetails. Everything is hunky dory up to the point where I try to acess the method insertScheme which is within the schemeSetup Class.
I have imported the schemeDetails script using the following:
import schemeDetails
reload(schemeDetails)
from schemeDetails import *
I can create the schemeDetails Object and access its attributes
d = schemeDetails.schemeSetup() -- fine
print(d.scheme) -- fine
d.insertScheme() -- throws error
but trying to call the insertScheme function throws an error
I don't know why this is happening as the import statement looks above board to me. Any advice appreciated
from sikuli import *
import os
class schemeSetup(object):
#Uses default values
def __init__(
self,
scheme = "GM",
cardNumber = "1234567A",
month = "December",
year = "2015",
setSchemeAsDefault = True):
#Provide default values for parameters
self.scheme = scheme
self.cardNumber = cardNumber
self.month = month
self.year = year
self.setSchemeAsDefault = setSchemeAsDefault
#schemeDetails is not a sub
# class of patient. It is simply defined within the patient class
# - there is a huge difference.
#====================================================#
#schemeDetails Function
def insertScheme(self):
print("insertScheme Works")
#r = Regions()
#r.description("Patient Maintenance", "schemeDetails")
#myRegion = r.createRegion()
#myRegion.highlight(1)
#click(myRegion.find(insertSchemeButton))
#click(myRegion.find(blankSchemeEntry))
#type(self.scheme + Key.ENTER + Key.ENTER)
#type(self.cardNumber + Key.ENTER)
#type(self.month + Key.ENTER)
#type(self.year + Key.ENTER)
#type(" ")
#unticks HT link, HT linking should be in a separate function
#====================================================#
#schemeDetails Function
def editScheme(self):
print("editScheme Works")
#====================================================#
def deleteScheme(self):
pass
#====================================================#
It may be of importance that calling either of the bottom functions does not produce an error. If I put print("Hello") under editScheme, and call that method using s.editScheme the program compiles but I get no output. If I run print(s.editScheme) it returns None
Well it seems to be fixed now after changing the import format to this
import schemeDetails
from schemeDetails import schemeSetup
s = schemeDetails.schemeSetup()