I'm new in programming and I need to write a code that create an odb that visualize max value of six field output of a single step. For every single node I would like represent the max value of each field output.
Now I've created a code which results in this this error:
myFieldOutput.addData(position=INTEGRATION_POINT, instance=instance1, data=maxStress)
omu_PrimArray from sequence failed - dimensions.
This is the code:
from abaqus import *
from abaqusConstants import *
import visualization
myViewport = session.Viewport(name='Max_Stess',
origin=(10, 10), width=150, height=100)
# Open the tutorial output database.
myOdb = visualization.openOdb(path='PROVA_04_10.odb', readOnly=False)
# Associate the output database with the viewport.
myViewport.setValues(displayedObject=myOdb)
instance1 = myOdb.rootAssembly.instances['MODIFICA_FUNZIONANTE']
# Create variables that refer to the first steps.
firstStep = myOdb.steps['sigma_equivalenti']
frame = firstStep.frames[-1]
#creo nuovo step
# lettura degli stress dallo step sigma
sigma_eq_1 = frame.fieldOutputs['sigma_eq_1']
sigma_eq_2 = frame.fieldOutputs['sigma_eq_2']
sigma_eq_3 = frame.fieldOutputs['sigma_eq_3']
sigma_eq_4 = frame.fieldOutputs['sigma_eq_4']
sigma_eq_5 = frame.fieldOutputs['sigma_eq_5']
sigma_eq_6 = frame.fieldOutputs['sigma_eq_6']
#calcolo del vettore degli sforzi massimi
maxStress=[]
for i in range(len(sigma_eq_1.values)):
v1=sigma_eq_1.values[i]
v2=sigma_eq_2.values[i]
v3=sigma_eq_3.values[i]
v4=sigma_eq_4.values[i]
v5=sigma_eq_5.values[i]
v6=sigma_eq_6.values[i]
maxStress.append((max(v1,v2,v3,v4,v5,v6),)) #max(valori)
myFieldOutput = frame.FieldOutput(name='tensioni_max',description='calcolo delle tensioni massime', type=SCALAR)
myFieldOutput.addData(position=INTEGRATION_POINT, instance=instance1, data=maxStress)
#visualizzazione della variabile delle sigma massima sul programma
myViewport.odbDisplay.setPrimaryVariable(field=myFieldOutput,outputPosition=INTEGRATION_POINT)
myViewport.odbDisplay.display.setValues(plotState=(CONTOURS_ON_DEF,))
You could use field argument to add the field output data as FieldOutput object. However, you should create the field data from already existing field outputs.
In your case, you could do the following:
Access the field output (NOT the field output data), as you did correctly.
sigma_eq_1 = frame.fieldOutputs['sigma_eq_1']
sigma_eq_2 = frame.fieldOutputs['sigma_eq_2']
sigma_eq_3 = frame.fieldOutputs['sigma_eq_3']
sigma_eq_4 = frame.fieldOutputs['sigma_eq_4']
sigma_eq_5 = frame.fieldOutputs['sigma_eq_5']
sigma_eq_6 = frame.fieldOutputs['sigma_eq_6']
Then, manipulate these field output data. You can do any feasible mathematical operation on these data, for ex. add, substract,etc. In this case, to find maximum value, we have specific command called maxEnvelope.
maxS = maxEnvelope([sigma_eq_1, sigma_eq_2, sigma_eq_3, sigma_eq_4, sigma_eq_5, sigma_eq_6])
Please note, this command takes list as an argument. And this command calculates the new field data at the same position where the original data is availble. In this case, it is available at Integration Point, hence it will be written at Integration Point.
3. Now, you could use field arugment to add field output data.
myFieldOutput = frame.FieldOutput(name='tensioni_max',description='calcolo delle tensioni massime', type=SCALAR)
myFieldOutput.addData(field=maxS[0])
P.S.: As you have imported visualization module as import visualization, you should use maxEnvelope method as visualization.maxEnvelope(...)
Related
Lets say I have an assembly like this:
MainProduct:
-Product1 (Instance of Part1)
-Product2 (Instance of Part2)
-Product3 (Instance of Part2)
-Product4 (Instance of Part3)
...
Now, I want to copy/paste a feature from Product3 into another one.
But I run into problems when selecting the feature programmatically, because there are 2 instances of the part of that feature.
I can't control which feature will be selected by CATIA.ActiveDocument.Selection.Add(myExtractReference)
Catia always selects the feature from Product2 instead of the feature from Product3. So the position of the pasted feature will be wrong!
Does anybody know this problem and has a solution to it?
Edit:
The feature reference which I want to copy already exists as a variable because it was newly created (an extract of selected geometry)
I could get help else where. Still want to share my solution. It's written in Python but in VBA its almost the same.
The clue is to access CATIA.Selection.Item(1).LeafProduct in order to know where the initial selection was made.
import win32com.client
import pycatia
CATIA = win32com.client.dynamic.DumbDispatch('CATIA.Application')
c_doc = CATIA.ActiveDocument
c_sel = c_doc.Selection
c_prod = c_doc.Product
# New part where the feature should be pasted
new_prod = c_prod.Products.AddNewComponent("Part", "")
new_part_doc = new_prod.ReferenceProduct.Parent
# from user selection
sel_obj = c_sel.Item(1).Value
sel_prod_by_user = c_sel.Item(1).LeafProduct # reference to the actual product where the selection was made
doc_from_sel = sel_prod_by_user.ReferenceProduct.Parent # part doc from selection
hb = doc_from_sel.Part.HybridBodies.Add() # new hybrid body for the extract. will be deleted later on
extract = doc_from_sel.Part.HybridShapeFactory.AddNewExtract(sel_obj)
hb.AppendHybridShape(extract)
doc_from_sel.Part.Update()
# Add the extract to the selection and copy it
c_sel.Clear()
c_sel.Add(extract)
sel_prod_by_catia = c_sel.Item(1).LeafProduct # reference to the product where Catia makes the selection
c_sel_copy() # will call Selection.Copy from VBA. Buggy in Python.
# Paste the extract into the new part in a new hybrid body
c_sel.Clear()
new_hb = new_part_doc.Part.HybridBodies.Item(1)
c_sel.Add(new_hb)
c_sel.PasteSpecial("CATPrtResultWithOutLink")
new_part_doc.Part.Update()
new_extract = new_hb.HybridShapes.Item(new_hb.HybridShapes.Count)
# Redo changes in the part, where the selection was made
c_sel.Clear()
c_sel.Add(hb)
c_sel.Delete()
# Create axis systems from Position object of sel_prd_by_user and sel_prd_by_catia
prod_list = [sel_prod_by_user, sel_prod_by_catia]
axs_list = []
for prod in prod_list:
pc_pos = pycatia.in_interfaces.position.Position(prod.Position) # conversion to pycata's Position object, necessary
# in order to use Position.GetComponents
ax_comp = pc_pos.get_components()
axs = new_part_doc.Part.AxisSystems.Add()
axs.PutOrigin(ax_comp[9:12])
axs.PutXAxis(ax_comp[0:3])
axs.PutYAxis(ax_comp[3:6])
axs.PutZAxis(ax_comp[6:9])
axs_list.append(axs)
new_part_doc.Part.Update()
# Translate the extract from axis system derived from sel_prd_by_catia to sel_prd_by_user
extract_ref = new_part_doc.Part.CreateReferenceFromObject(new_extract)
tgt_ax_ref = new_part_doc.Part.CreateReferenceFromObject(axs_list[0])
ref_ax_ref = new_part_doc.Part.CreateReferenceFromObject(axs_list[1])
new_extract_translated = new_part_doc.Part.HybridShapeFactory.AddNewAxisToAxis(extract_ref, ref_ax_ref, tgt_ax_ref)
new_hb.AppendHybridShape(new_extract_translated)
new_part_doc.Part.Update()
I would suggest a differed approach. Instead of adding references you get from somewhere (by name probably) add the actual instance of part to selection while iterating trough all the products. Or use instance Names to get the correct part.
Here is a simple VBA example of iterating one lvl tree and select copy paste scenario.
If you want to copy features, you have to dive deeper on the Instance objects.
Public Sub CatMain()
Dim ActiveDoc As ProductDocument
Dim ActiveSel As Selection
If TypeOf CATIA.ActiveDocument Is ProductDocument Then 'of all the checks that people are using I think this one is most elegant and reliable
Set ActiveDoc = CATIA.ActiveDocument
Set ActiveSel = ActiveDoc.Selection
Else
Exit Sub
End If
Dim Instance As Product
For Each Instance In ActiveDoc.Product.Products 'object oriented for ideal for us in this scenario
If Instance.Products.Count = 0 Then 'beware that products without parts have also 0 items and are therefore mistaken for parts
Call ActiveSel.Add(Instance)
End If
Next
Call ActiveSel.Copy
Call ActiveSel.Clear
Dim NewDoc As ProductDocument
Set NewDoc = CATIA.Documents.Add("CATProduct")
Set ActiveSel = NewDoc.Selection
Call ActiveSel.Add(NewDoc.Product)
Call ActiveSel.Paste
Call ActiveSel.Clear
End Sub
I would like to create a contour plot of stiffness from field output results. For this purpose I have to divide NFORC2 (Y component of nodal force vector) by U2 (displacement in Y direction).
I tried to use Create Field Output --> From Fields where we can define our own output variables. Scalars can be extracted from vectors using getScalarField() but Abaqus shows an error because NFORC is whole element variable while U is nodal variable.
Thus it seems that the only way is to write a script that will convert NFORC. I've found a code that can save a variable as element nodal. It was designed for stress which is calculated at integration points so I'm not sure that it will convert NFORC properly but it's the only option I have so far. It saves some output so I assume that it's correct.
However, Abaqus still doesn't let me divide this new variable by U2. It seems that I have to convert it to unique nodal first. For this I've found another Python script and added it to the first one. Apparently I did something wrong because the error shows up.
Here are the two scripts combined into one:
from abaqusConstants import *
from odbAccess import *
import numpy as np
# ***********************************************
odbPath="path_to_odb_file"
stepName="Step-1"
frameNumber=-1 #last frame in the stepName
sourceOutputFieldName='NFORC2' #element forces field
newOutputFieldName='NFORC2_at_NODES_UNIQUE'
# ************************************************
odb=session.openOdb(name=odbPath,readOnly=FALSE)
step=odb.steps[stepName]
frame=step.frames[frameNumber]
sourceField=frame.fieldOutputs[sourceOutputFieldName]
subField=sourceField.getSubset(position=ELEMENT_NODAL)
Values=subField.bulkDataBlocks[0].data
NodeLabels=subField.bulkDataBlocks[0].nodeLabels
NodeLabels_unique, unq_idx = np.unique(NodeLabels, return_inverse=True)
Values_Averaged=np.zeros((NodeLabels_unique.size,Values.shape[1]))
unq_counts = np.bincount(unq_idx)
for i in xrange(0,Values.shape[1]):
ValuesTemp = [item[i] for item in Values]
unq_sum = np.bincount(unq_idx, weights=ValuesTemp)
Values_Averaged[:,i] = unq_sum / unq_counts
newField=frame.FieldOutput(name=newOutputFieldName, field=Values_Averaged)
odb.save()
odb.close()
The error I get points to the following line of code:
newField=frame.FieldOutput(name=newOutputFieldName, field=Values_Averaged)
The error message is: TypeError: keyword error on field
Do you know what may be causing the error and how the script should look like?
UPDATE: I finally got this working. Here's the fixed script (odb has to be opened without "Read only" option):
from abaqusConstants import *
from odbAccess import *
import numpy as np
# ***********************************************
odbPath="path_to_odb_file"
stepName="Step-1"
frameNumber=-1 #last frame in the stepName
sourceOutputFieldName='NFORC2' #element forces field
newOutputFieldName='NFORC2_at_NODES_UNIQUE'
# ************************************************
odb=session.openOdb(name=odbPath,readOnly=FALSE)
step=odb.steps[stepName]
frame=step.frames[frameNumber]
AllInstances=(odb.rootAssembly.instances.keys())
MyInstance=(AllInstances[-1])
instance1=odb.rootAssembly.instances[MyInstance]
sourceField=frame.fieldOutputs[sourceOutputFieldName]
subField=sourceField.getSubset(position=ELEMENT_NODAL)
Values=subField.bulkDataBlocks[0].data
NodeLabels=subField.bulkDataBlocks[0].nodeLabels
NodeLabels_unique, unq_idx = np.unique(NodeLabels, return_inverse=True)
Values_Averaged=np.zeros((NodeLabels_unique.size,Values.shape[1]))
unq_counts = np.bincount(unq_idx)
for i in xrange(0,Values.shape[1]):
ValuesTemp = [item[i] for item in Values]
unq_sum = np.bincount(unq_idx, weights=ValuesTemp)
Values_Averaged[:,i] = unq_sum / unq_counts
newField=frame.FieldOutput(name=newOutputFieldName,type=SCALAR, description="field")
newField.addData(position=NODAL, instance=instance1, labels=NodeLabels_unique, data=Values_Averaged)
odb.save()
odb.close()
The new "NFORC2_at_NODES_UNIQUE" field is correctly created. The only problem now is that when I divide this field by U2 displacement using Create Field Output --> From Fields, I get division by zero error. It's understandable because displacement can be zero in some locations. But what can be done in this case? Perhaps I should convert zeros to some very low values in my script. How can I do this?
Or maybe a better way would be to force the script to return 0 for each encountered division by zero.
I have two files, one an esri shapefile (.shp), the other a point cloud (.las).
Using laspy and shapefile modules I've managed to find which points of the .las file fall within specific polygons of the shapefile. What I now wish to do is to add an index number that enables identification between the two datasets. So e.g. all points that fall within polygon 231 should get number 231.
The problem is that as of yet I'm unable to append anything to the list of points when writing the .las file. The piece of code that I'm trying to do it in is here:
outFile1 = laspy.file.File("laswrite2.las", mode = "w",header = inFile.header)
outFile1.points = truepoints
outFile1.points.append(indexfromshp)
outFile1.close()
The error I'm getting now is: AttributeError: 'numpy.ndarray' object has no attribute 'append'. I've tried multiple things already including np.append but I'm really at a loss here as to how to add anything to the las file.
Any help is much appreciated!
There are several ways to do this.
Las files have classification field, you could store the indexes in this field
las_file = laspy.file.File("las.las", mode="rw")
las_file.classification = indexfromshp
However if the Las file has version <= 1.2 the classification field can only store values in the range [0, 35], but you can use the 'user_data' field which can hold values in the range [0, 255].
Or if you need to store values higher than 255 / you need a separate field you can define a new dimension (see laspy's doc on how to add extra dimensions).
Your code should be close to something like this
outFile1 = laspy.file.File("laswrite2.las", mode = "w",header = inFile.header)
# copy fields
for dimension in inFile.point_format:
dat = inFile.reader.get_dimension(dimension.name)
outFile1.writer.set_dimension(dimension.name, dat)
outFile1.define_new_dimension(
name="index_from_shape",
data_type=7, # uint64_t
description = "Index of corresponding polygon from shape file"
)
outFile1.index_from_shape = indexfromshp
outFile1.close()
I am trying to understand why I must store the output of a Python function (regardless of the name of the variable I use, and regardless of whether I subsequently use that variable). I think this is more general to Python and not specifically to the software NEURON, thus I put it here on Stackoverflow.
The line of interest is here:
clamp_output = attach_current_clamp(cell)
If I just write attach_current_clamp(cell), without storing the output of the function into a variable, the code does not work (plot is empty), and yet I don't use clamp_output at all. Why cannot I not just call the function? Why must I use a variable to store the output even without using the output?
import sys
import numpy
sys.path.append('/Applications/NEURON-7.4/nrn/lib/python')
from neuron import h, gui
from matplotlib import pyplot
#SET UP CELL
class SingleCell(object):
def __init__(self):
self.soma = h.Section(name='soma', cell=self)
self.soma.L = self.soma.diam = 12.6517
self.all = h.SectionList()
self.all.wholetree(sec=self.soma)
self.soma.insert('pas')
self.soma.e_pas = -65
for sec in self.all:
sec.cm = 20
#CURRENT CLAMP
def attach_current_clamp(cell):
stim = h.IClamp(cell.soma(1))
stim.delay = 100
stim.dur = 300
stim.amp = 0.2
return stim
cell = SingleCell()
#IF I CALL THIS FUNCTION WITHOUT STORING THE OUTPUT, THEN IT DOES NOT WORK
clamp_output = attach_current_clamp(cell)
#RECORD AND PLOT
soma_v_vec = h.Vector()
t_vec = h.Vector()
soma_v_vec.record(cell.soma(0.5)._ref_v)
t_vec.record(h._ref_t)
h.tstop = 800
h.run()
pyplot.figure(figsize=(8,4))
soma_plot = pyplot.plot(t_vec,soma_v_vec)
pyplot.show()
This is a NEURON+Python specific bug/feature. It has to do with Python garbage collection and the way NEURON implements the Python-HOC interface.
When there are no more references to a NEURON object (e.g. the IClamp) from within Python or HOC, the object is removed from NEURON.
Saving the IClamp as a property of the cell averts the problem in the same way as saving the result, so that could be an option for you:
# In __init__:
self.IClamps = []
# In attach_current_clamp:
stim.amp = 0.2
cell.IClamps.append(stim)
#return stim
I was wondering why i'm getting this error for the following code, as I have defined ref_atoms as ['CA']. The error occurs in line 121 where the superimposer is initiated for following line of code super_imposer.set_atoms(ref_atoms, sample_atoms)
def alignPDB(potentialTag,tagProtein):
# Select what residues numbers you wish to align
# and put them in a list
start_id = 1
end_id = 10
atoms_to_be_aligned = range(start_id, end_id + 1)
# Start the parser
pdb_parser = Bio.PDB.PDBParser(QUIET = True)
# Get the structures
ref_structure = pdb_parser.get_structure("tagProtein", "4ABN.pdb")
sample_structure = pdb_parser.get_structure("potentialTag", "2LYZ.pdb")
# Use the first model in the pdb-files for alignment
# Change the number 0 if you want to align to another structure
ref_model = ref_structure[0]
sample_model = sample_structure[0]
# Make a list of the atoms (in the structures) you wish to align.
# In this case we use CA atoms whose index is in the specified range
ref_atoms = ['CA']
sample_atoms = ['CA']
# Iterate of all chains in the model in order to find all residues
for ref_chain in ref_model:
# Iterate of all residues in each model in order to find proper atoms
for ref_res in ref_chain:
# Check if residue number ( .get_id() ) is in the list
if ref_res.get_id()[1] in atoms_to_be_aligned:
# Append CA atom to list
ref_atoms.append(ref_res['CA'])
# Do the same for the sample structure
for sample_chain in sample_model:
for sample_res in sample_chain:
if sample_res.get_id()[1] in atoms_to_be_aligned:
sample_atoms.append(sample_res['CA'])
# Now we initiate the superimposer:
super_imposer = Bio.PDB.Superimposer()
super_imposer.set_atoms(ref_atoms, sample_atoms)
super_imposer.apply(sample_model.get_atoms())
# Print RMSD:
print super_imposer.rms
# Save the aligned version of 1UBQ.pdb
io = Bio.PDB.PDBIO()
io.set_structure(sample_structure)
io.save("2LYZ_aligned.pdb")