Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lightfield sensor and source #123

Closed
wants to merge 11 commits into from
49 changes: 49 additions & 0 deletions ansys_optical_automation/application/Source_to_Lightfield.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Python Script, API Version = V23
"""
The aim of this script is to convert any type of lightsource (surface and rayfile source currently) into Lightfield one.
12/2022 V1.0 capabilities :
-
"""
from ansys_optical_automation.speos_process.speos_sensors import LightFieldSensor
from ansys_optical_automation.speos_process.speos_sensors import LocalMeshing

# import sys
# repo_path = r"your_repo_path"
# sys.path.append(repo_path)


def import_Dome(path):
world_origin = GetRootPart().CoordinateSystems[-1]
Selection.Create(world_origin).SetActive()
DocumentInsert.Execute(path)


def set_dome(surface_name, size):
dome_surface = Selection.CreateByNames(surface_name)
InputHelper.PauseAndGetInput("Please enter a scale value", size)
world_origin_point = GetRootPart().CoordinateSystems[-1].Frame.Origin
Scale.Execute(dome_surface, world_origin_point, size)


def set_LocalMeshing(geometries, name, sag_mode, sag_value):
localMeshing = LocalMeshing(name, SpeosSim, SpaceClaim)
localMeshing.set_geometries(geometries)
localMeshing.set_sag(sag_mode, sag_value)


def define_LightfieldSensor(sensor_name, sensor_type, incident_sampling, azimuth_sampling, geometries):
lightField = LightFieldSensor(sensor_name, SpeosSim, SpaceClaim)
lightField.set_faces(geometries)
lightField.set_type(sensor_type)
lightField.set_sampling(incident_sampling, azimuth_sampling)


def define_DirectSim(sim_name, sensor_name):
pass


def main():
pass


main()
2 changes: 1 addition & 1 deletion ansys_optical_automation/application/camera_nhtsa_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def prepare_sim_setup(cam_name, sim_name, part_names, cam_model):
"""
Prepares a simulation model based on the given input:
creates/edits the Camera with name cam_name based on the predefined Ccam_model,
positions it at axissystem "Cam_pos_1"
positions it at axis system "Cam_pos_1"
creates/edits the Simulation with name sim_name
adds all geometries of the parts given in part_names
Parameters
Expand Down
138 changes: 138 additions & 0 deletions ansys_optical_automation/speos_process/speos_geometry_properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from ansys_optical_automation.scdm_core.base import BaseSCDM


class GeometryProperties(BaseSCDM):
"""
Provides the parent class for all Speos Geometry properties types.

This class contains methods and properties that are common to all geometry properties elements.
It shouldn't be used by itself. Subclasses should be used instead.
"""

def __init__(self, name, SpeosSim, SpaceClaim):
super(GeometryProperties, self).__init__(SpaceClaim, ["V19", "V20", "V21", "V22", "V23"])
self.speos_sim = SpeosSim
self.name = name
self.speos_object = None
self.geometries_list = []

def set_geometries(self, geometries):
"""
set geometries, e.g. bodies and faces, to Speos geometry properties.

Parameters
----------
geometries : list
a list of SCDM bodies and faces

Returns
-------


"""
if len(self.geometries_list) == 0:
selection = self.Selection.Create(geometries)
self.speos_object.Geometries.Set(selection.Items)
else:
self.geometries_list.extend(geometries)
selection = self.Selection.Create(self.geometries_list)
self.speos_object.Geometries.Set(selection.Items)


# TODO add unittest
class LocalMeshing(GeometryProperties):
"""
Provides methods for defining the Speos LocalMeshing.
"""

def __init__(self, name, SpeosSim, SpaceClaim):
super(LocalMeshing, self).__init__(name, SpeosSim, SpaceClaim)
if self.speos_sim.LocalMeshing.Find(name):
self.speos_object = self.speos_sim.LocalMeshing.Find(name)
for item in self.speos_object.Geometries.LinkedObjects:
self.geometries_list.append(item)
else:
self.speos_object = self.speos_sim.LocalMeshing.Create()
self.speos_object.Name = name

def set_sag(self, sag_mode, sag_value):
"""
Define Sag Mode and apply a value on it.
Parameters
----------
sag_mode : str
In Sag Meshing, 3 kind of modes are available.

sag_value : float
Meshing value. Depending of sag_mode value, sag_value might be an int or a float.

Returns
-------


"""
sag_mode = sag_mode.lower()
if sag_mode == "proportional to face size":
self.speos_object.MeshingSagMode = self.speos_sim.LocalMeshing.EnumMeshingSagMode.ProportionalFace
float(sag_value)
self.speos_object.MeshingSagValue = sag_value
elif sag_mode == "proportional to body size":
self.speos_object.MeshingSagMode = self.speos_sim.LocalMeshing.EnumMeshingSagMode.ProportionalBody
float(sag_value)
self.speos_object.MeshingSagValue = sag_value
elif sag_mode == "fixed":
self.speos_object.MeshingSagMode = self.speos_sim.LocalMeshing.EnumMeshingSagMode.Fixed
float(sag_value)
self.speos_object.MeshingSagValue = sag_value
else:
error_message = "please provide a valid Sag Mode"
raise ValueError(error_message)

def set_step(self, step_mode, step_value):
"""
Define step values for local meshing.

Parameters
----------
step_mode : str
step mode
step_value : float
step value

Returns
-------


"""
step_mode = step_mode.lower()
if step_mode == "proportional to face size":
self.speos_object.MeshingStepMode = self.speos_sim.LocalMeshing.EnumMeshingStepMode.ProportionalFace
float(step_value)
self.speos_object.MeshingStepValue = step_value
elif step_mode == "proportional to body size":
self.speos_object.MeshingStepMode = self.speos_sim.LocalMeshing.EnumMeshingStepMode.ProportionalBody
float(step_value)
self.speos_object.MeshingStepValue = step_value
elif step_mode == "fixed":
self.speos_object.MeshingStepMode = self.speos_sim.LocalMeshing.EnumMeshingStepMode.Fixed
float(step_value)
self.speos_object.MeshingStepValue = step_value
else:
error_message = "please provide a valid Sag Mode"
raise ValueError(error_message)


class UVMapping(GeometryProperties):
"""
Provides methods for defining the Speos UVMapping.
"""

def __init__(self, name, SpeosSim, SpaceClaim):
super(UVMapping, self).__init__(name, SpeosSim, SpaceClaim)
if self.speos_sim.LocalMeshing.Find(name):
self.speos_object = self.speos_sim.UVMapping.Find(name)
for item in self.speos_object.Geometries.LinkedObjects:
self.geometries_list.append(item)
else:
self.speos_object = self.speos_sim.UVMapping.Create()
self.speos_object.Name = name
91 changes: 91 additions & 0 deletions ansys_optical_automation/speos_process/speos_sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,3 +679,94 @@ def set_fov(self, horizontal_fov, vertical_fov, horizontal_sampling, vertical_sa
self.speos_object.VPlane = vertical_fov
self.speos_object.HNbSamples = horizontal_sampling
self.speos_object.VNbSamples = vertical_sampling


class SensorLightField(Sensor):
"""
LightFieldSensor has to be computed after its definition by using command like this: object.Compute()
"""

def __init__(self, name, SpeosSim, SpaceClaim):
super(SensorLightField, self).__init__(name, SpeosSim, SpaceClaim)
speos_object = self.speos_sim.SensorLightField.Find(self.name)
if not speos_object:
speos_object = self.speos_sim.SensorLightField.Create()
speos_object.Name = name
self.speos_object = speos_object

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing the wavelength settings -> start end+ res

def set_faces(self, selection):
# TODO please correct this method and comment section
"""
Make the faces selection and apply them in Lightfield Sensor
Parameters
----------
selection : active selection
return a list?

Returns
-------


"""
face_selection = self.Selection.Create(selection)
self.speos_sim.SensorLightField.OrientedFaces.Set(face_selection.Items)

def set_type(self, sensor_type):
# TODO double check if everything is fine: Just a copy/past from Radiance sensor set_type function with small
# adaptations
"""
Set Sensor Type for Lightfield sensor. Only Radiometric, Photometric and Spectral are available for it.
Parameters
----------
sensor_type : str
return the stype of sensor

Returns
-------


"""
sensor_type = sensor_type.lower()
if sensor_type == "photometric":
self.speos_object.SensorType = self.speos_sim.SensorLightfield.EnumSensorType.Photometric
elif sensor_type == "radiometric":
self.speos_object.SensorType = self.speos_sim.SensorLightfield.EnumSensorType.Radiometric
elif sensor_type == "spectral":
self.speos_object.SensorType = self.speos_sim.SensorLightfield.EnumSensorType.Spectral
else:
error_message = "please provide a valid Lightfield sensor type"
raise ValueError(error_message)

def set_sampling(self, incident_sampling=None, azimuth_sampling=None):
"""Set the number of samples on the axes.

Parameters
----------
incident_sampling : int, optionl
Number of samples on the incident angle. The default is ``None``.
azimuth_sampling : int
Number of samples on the azimuth_sampling. The default is ``None``.
"""
if not incident_sampling and not azimuth_sampling:
raise NameError("No inputs provided.")
if incident_sampling:
self.speos_object.IncidentAngleSamples = incident_sampling
if azimuth_sampling:
self.speos_object.AzimuthAngleNbSamples = azimuth_sampling

def set_resolution(self, incident_resolution=None, azimuth_resolution=None):
"""Set the number of samples on the axes.

Parameters
----------
incident_resolution : int, optionl
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this hsould be a float as it can be 0.5 degree

Number of resolution on the incident angle. The default is ``None``.
azimuth_resolution : int
Number of resolution on the azimuth_sampling. The default is ``None``.
"""
if not incident_resolution and not azimuth_resolution:
raise NameError("No inputs provided.")
if incident_resolution:
self.speos_object.IncidentAngleResolution = incident_resolution
if azimuth_resolution:
self.speos_object.AzimuthAngleResolution = azimuth_resolution
23 changes: 23 additions & 0 deletions ansys_optical_automation/speos_process/speos_simulations.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,26 @@ def linked_export_simulation(self):
save_path, r"SPEOS isolated files", os.path.basename(doc_path).split(".")[0], export_name, export_name
)
return sim_path

def append_source(simulation_name):
"""
Append a list of source in a simulation.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add correct doc string

Returns
-------

"""
speos_source_list = []
for items in GetRootPart().CustomObjects:
if items.Type == "SPEOS_SC.SIM.SpeosWrapperSourceSurface":
Copy link
Collaborator

@StefanThoene StefanThoene Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use correct speos API

Suggested change
if items.Type == "SPEOS_SC.SIM.SpeosWrapperSourceSurface":
if SpeosSim.SourceSurface.Find(items.GetName()):

speos_source_list.append(items)
if items.Type == "SPEOS_SC.SIM.SpeosWrapperSourceRayFile":
speos_source_list.append(items)
else:
print("No Light source found")

Direct_Sim = SpeosSim.SimulationDirect.Find(simulation_name)
for source_index in range(Direct_Sim.Sources.Count):
source_sim = Direct_Sim.Sources.Item[source_index]
speos_source_list.append(source_sim)
Direct_Sim.Sources.Set(speos_source_list)
return speos_source_list
30 changes: 30 additions & 0 deletions ansys_optical_automation/speos_process/speos_sources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from ansys_optical_automation.scdm_core.base import BaseSCDM


class Source(BaseSCDM):
"""
Provides the parent class for all Speos Source types.

This class contains methods and properties that are common to all Source elements.
It shouldn't be used by itself. Subclasses should be used instead.
"""

def __init__(self, name, SpeosSim, SpaceClaim):
super(Source, self).__init__(SpaceClaim, ["V19", "V20", "V21", "V22", "V23"])
self.speos_sim = SpeosSim
self.name = name
self.speos_object = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add some values all sources have in comon E.g. Power, spectrum, intensity type ...



class SourceLightField(Source):
"""
Provides methods for defining the Speos LocalMeshing.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please adjust docstring

"""

def __init__(self, name, SpeosSim, SpaceClaim):
super(SourceLightField, self).__init__(name, SpeosSim, SpaceClaim)
if self.speos_sim.SourceLightField.Find(self.name):
self.speos_object = self.speos_sim.SourceLightField.Find(self.name)
else:
self.speos_object = self.speos_sim.SourceLightField.Create()
self.speos_object.Name = self.name