diff --git a/docker-compose.yml b/docker-compose.yml index ca1a25260..f49d51ca7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.4" services: optics_speos-rpc: - image: ghcr.io/pyansys/pyoptics/speos-rpc:2023.2.0.666 + image: ghcr.io/pyansys/pyoptics/speos-rpc:2024.1.0.686 container_name: optics_speos-rpc ports: - "50051:50051" diff --git a/pyproject.toml b/pyproject.toml index 2a79b94d1..e0dc09a19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ classifiers=[ dependencies=[ "grpcio==1.51.3", "grpcio-tools==1.48.2", - "ansys-api-speos==0.2.0", + "ansys-api-speos==0.3.0", ] [project.optional-dependencies] diff --git a/tests/assets/Inverse_SeveralSensors.speos/CameraDistortion.OPTDistortion b/tests/assets/Inverse_SeveralSensors.speos/CameraDistortion.OPTDistortion new file mode 100644 index 000000000..0c7813b78 --- /dev/null +++ b/tests/assets/Inverse_SeveralSensors.speos/CameraDistortion.OPTDistortion @@ -0,0 +1,55 @@ +OPTIS - Optical distortion file v1.0 +created by LMR 2011-01-22 +0 +51 +0.0000 0.0000 +0.0227 0.0211 +0.0454 0.0421 +0.0681 0.0631 +0.0908 0.0840 +0.1134 0.1048 +0.1361 0.1255 +0.1588 0.1461 +0.1815 0.1665 +0.2042 0.1868 +0.2269 0.2069 +0.2496 0.2268 +0.2723 0.2465 +0.2950 0.2660 +0.3176 0.2852 +0.3403 0.3043 +0.3630 0.3231 +0.3857 0.3416 +0.4084 0.3599 +0.4311 0.3779 +0.4538 0.3956 +0.4765 0.4131 +0.4992 0.4302 +0.5219 0.4471 +0.5445 0.4637 +0.5672 0.4800 +0.5899 0.4961 +0.6126 0.5118 +0.6353 0.5273 +0.6580 0.5424 +0.6807 0.5573 +0.7034 0.5719 +0.7261 0.5862 +0.7487 0.6002 +0.7714 0.6139 +0.7941 0.6274 +0.8168 0.6406 +0.8395 0.6535 +0.8622 0.6662 +0.8849 0.6786 +0.9076 0.6907 +0.9303 0.7026 +0.9529 0.7143 +0.9756 0.7257 +0.9983 0.7368 +1.0210 0.7478 +1.0437 0.7585 +1.0664 0.7690 +1.0891 0.7792 +1.1118 0.7893 +1.1345 0.7991 diff --git a/tests/assets/Inverse_SeveralSensors.speos/Inverse_SeveralSensors.speos b/tests/assets/Inverse_SeveralSensors.speos/Inverse_SeveralSensors.speos new file mode 100644 index 000000000..418157726 Binary files /dev/null and b/tests/assets/Inverse_SeveralSensors.speos/Inverse_SeveralSensors.speos differ diff --git a/tests/test_job.py b/tests/test_job.py index 5a96105bd..3181bca26 100644 --- a/tests/test_job.py +++ b/tests/test_job.py @@ -51,10 +51,13 @@ def test_job(): simulation__v1__pb2.Load_Request(guid=simu_create_res.guid, input_file_path=speos_simulation_full_path) ) - # Allocate job from simu - job_create_res = job_manager_stub.Create( - job__v1__pb2.Create_Request(simu_guid=simu_create_res.guid, job_type=job__v1__pb2.Job_Type.CPU) - ) + # Allocate job from simu guid, job type and simu properties + j = job__v1__pb2.Job() + j.simu_guid = simu_create_res.guid + j.job_type = job__v1__pb2.Job_Type.CPU + j.direct_mc_simulation_properties.stop_condition_rays_number = 500000 + j.direct_mc_simulation_properties.automatic_save_frequency = 60 + job_create_res = job_manager_stub.Create(job__v1__pb2.Create_Request(job=j)) # Start the job job_stub.Start(job__v1__pb2.Start_Request(guid=job_create_res.guid)) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 96e595663..0a864a72b 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -60,7 +60,7 @@ def test_create_camera_sensor(): distortion = os.path.join(camera_input_files_path, "CameraDistortion.OPTDistortion") camera_t = sensor_pb2.SensorTemplate() - camera_t.camera_sensor_template.sensor_name = "CameraSensorPhotometric" + camera_t.name = "CameraSensorPhotometric" camera_t.camera_sensor_template.sensor_mode_photometric.transmittance_file_uri = transmittance camera_t.camera_sensor_template.sensor_mode_photometric.gamma_correction = 2.2 camera_t.camera_sensor_template.sensor_mode_photometric.color_mode_color.red_spectrum_file_uri = red_spectrum @@ -83,7 +83,7 @@ def test_create_camera_sensor(): # Create a camera sensor using template + properties camera_sensor = simulation_pb2.Sensor() - camera_sensor.name = camera_t.camera_sensor_template.sensor_name + "_1" + camera_sensor.name = camera_t.name + "_1" camera_sensor.guid = cam_sensor_create_res.guid camera_sensor.camera_sensor_properties.sensor_position.origin[:] = [25.0, 0.0, 0.0] @@ -103,8 +103,12 @@ def test_create_camera_sensor(): target="localhost:" + str(config.get("SpeosServerPort")), stub_type=job_pb2_grpc.SpeosJobsManagerStub, ) - job_create_req = job_pb2.Create_Request(simu_guid=simu_create_res.guid, job_type=job_pb2.Job_Type.CPU) - job_create_res = job_manager_stub.Create(job_create_req) + j = job_pb2.Job() + j.simu_guid = simu_create_res.guid + j.job_type = job_pb2.Job_Type.CPU + j.inverse_mc_simulation_properties.optimized_propagation_none.stop_condition_passes_number = 5 + j.inverse_mc_simulation_properties.automatic_save_frequency = 1800 + job_create_res = job_manager_stub.Create(job_pb2.Create_Request(job=j)) # Start the job job_stub = grpc_stub.get_stub_insecure_channel( diff --git a/tests/test_simulation.py b/tests/test_simulation.py index 726067151..d77ba6063 100644 --- a/tests/test_simulation.py +++ b/tests/test_simulation.py @@ -7,65 +7,73 @@ .. code:: $ pytest --cov ansys.pyoptics.speos """ +import json import os import shutil +import time from ansys.api.speos import grpc_stub -from ansys.api.speos.file.v1 import file_transfer -import ansys.api.speos.file.v1.file_transfer_pb2 as file_transfer__v1__pb2 -import ansys.api.speos.file.v1.file_transfer_pb2_grpc as file_transfer__v1__pb2_grpc -import ansys.api.speos.simulation.v1.simulation_pb2 as simulation__v1__pb2 -import ansys.api.speos.simulation.v1.simulation_pb2_grpc as simulation__v1__pb2_grpc +from ansys.api.speos.file.v1 import file_transfer, file_transfer_pb2, file_transfer_pb2_grpc +from ansys.api.speos.job.v1 import job_pb2, job_pb2_grpc +from ansys.api.speos.simulation.v1 import ( + simulation_pb2, + simulation_pb2_grpc, + simulation_template_pb2, + simulation_template_pb2_grpc, +) +import grpc +import pytest from conftest import config, local_test_path, test_path +import helper def test_simulation(): # Stub on simulation manager simulation_manager_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=simulation__v1__pb2_grpc.SimulationsManagerStub, + stub_type=simulation_pb2_grpc.SimulationsManagerStub, ) # Stub on simulation simulation_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=simulation__v1__pb2_grpc.SpeosSimulationStub, + stub_type=simulation_pb2_grpc.SpeosSimulationStub, ) # Create a new simulation on the server - guid_simu = simulation_manager_stub.Create(simulation__v1__pb2.Create_Request()) + guid_simu = simulation_manager_stub.Create(simulation_pb2.Create_Request()) # Get input file path and load it speos_simulation_name = "LG_50M_Colorimetric_short.sv5" folder_path = os.path.join(test_path, speos_simulation_name) speos_simulation_full_path = os.path.join(folder_path, speos_simulation_name) - load_request = simulation__v1__pb2.Load_Request() + load_request = simulation_pb2.Load_Request() load_request.guid = guid_simu.guid load_request.input_file_path = speos_simulation_full_path simulation_stub.Load(load_request) # Delete simulation - delete_request = simulation__v1__pb2.Delete_Request() + delete_request = simulation_pb2.Delete_Request() delete_request.guid = guid_simu.guid simulation_manager_stub.Delete(delete_request) -def test_simu_allocateSyst_load_run_with_file_transfer(): +def test_simu_allocateSyst_load_with_file_transfer(): # Stubs creations file_transfer_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=file_transfer__v1__pb2_grpc.FileTransferServiceStub, + stub_type=file_transfer_pb2_grpc.FileTransferServiceStub, ) simu_manager_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=simulation__v1__pb2_grpc.SimulationsManagerStub, + stub_type=simulation_pb2_grpc.SimulationsManagerStub, ) simu_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=simulation__v1__pb2_grpc.SpeosSimulationStub, + stub_type=simulation_pb2_grpc.SpeosSimulationStub, ) # Use upload_folder helper provided within ansys.api.speos.file.v1 @@ -78,29 +86,29 @@ def test_simu_allocateSyst_load_run_with_file_transfer(): sv5_res_uri = [upload_res.info.uri for upload_res in upload_responses if upload_res.info.file_name == sv5_name][0] # Allocate simulation - create_res = simu_manager_stub.Create(simulation__v1__pb2.Create_Request()) + create_res = simu_manager_stub.Create(simulation_pb2.Create_Request()) # Load sv5 into allocated simulation - simu_stub.Load(simulation__v1__pb2.Load_Request(guid=create_res.guid, input_file_path=sv5_res_uri)) + simu_stub.Load(simulation_pb2.Load_Request(guid=create_res.guid, input_file_path=sv5_res_uri)) # Delete files on Server # Files uploaded - file_transfer_stub.Delete(file_transfer__v1__pb2.Delete_Request(uri=sv5_res_uri)) + file_transfer_stub.Delete(file_transfer_pb2.Delete_Request(uri=sv5_res_uri)) def test_simu_allocateSyst_load_save_with_file_transfer(): # Stubs creations file_transfer_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=file_transfer__v1__pb2_grpc.FileTransferServiceStub, + stub_type=file_transfer_pb2_grpc.FileTransferServiceStub, ) simu_manager_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=simulation__v1__pb2_grpc.SimulationsManagerStub, + stub_type=simulation_pb2_grpc.SimulationsManagerStub, ) simu_stub = grpc_stub.get_stub_insecure_channel( target="localhost:" + str(config.get("SpeosServerPort")), - stub_type=simulation__v1__pb2_grpc.SpeosSimulationStub, + stub_type=simulation_pb2_grpc.SpeosSimulationStub, ) sv5_name = "LG_50M_Colorimetric_short.sv5" blue_spectrum = "Blue Spectrum.spectrum" @@ -115,15 +123,15 @@ def test_simu_allocateSyst_load_save_with_file_transfer(): sv5_res_uri = [upload_res.info.uri for upload_res in upload_responses if upload_res.info.file_name == sv5_name][0] # Allocate simulation - create_res = simu_manager_stub.Create(simulation__v1__pb2.Create_Request()) + create_res = simu_manager_stub.Create(simulation_pb2.Create_Request()) # Load sv5 into allocated simulation - simu_stub.Load(simulation__v1__pb2.Load_Request(guid=create_res.guid, input_file_path=sv5_res_uri)) + simu_stub.Load(simulation_pb2.Load_Request(guid=create_res.guid, input_file_path=sv5_res_uri)) # Reserve an item in file system in order to perform a Save - reserve_res = file_transfer_stub.Reserve(file_transfer__v1__pb2.Reserve_Request()) + reserve_res = file_transfer_stub.Reserve(file_transfer_pb2.Reserve_Request()) # And Save - simu_stub.Save(simulation__v1__pb2.Save_Request(guid=create_res.guid, input_folder_path=reserve_res.uri)) + simu_stub.Save(simulation_pb2.Save_Request(guid=create_res.guid, input_folder_path=reserve_res.uri)) # Download locally the simu saved - using download_folder helper provided within ansys.api.speos.file.v1 download_loc = os.path.join(local_test_path, "download_simu") @@ -141,6 +149,130 @@ def test_simu_allocateSyst_load_save_with_file_transfer(): # Delete files on Server # Files uploaded - file_transfer_stub.Delete(file_transfer__v1__pb2.Delete_Request(uri=sv5_res_uri)) + file_transfer_stub.Delete(file_transfer_pb2.Delete_Request(uri=sv5_res_uri)) # Files saved - file_transfer_stub.Delete(file_transfer__v1__pb2.Delete_Request(uri=reserve_res.uri)) + file_transfer_stub.Delete(file_transfer_pb2.Delete_Request(uri=reserve_res.uri)) + + +def test_simu_load_read_update(): + # Create empty Simulation + simu_manager_stub = grpc_stub.get_stub_insecure_channel( + target="localhost:" + str(config.get("SpeosServerPort")), + stub_type=simulation_pb2_grpc.SimulationsManagerStub, + ) + simu_create_res = simu_manager_stub.Create(simulation_pb2.Create_Request()) + + # Load speos file into allocated simulation + sv5_path = os.path.join(test_path, "Inverse_SeveralSensors.speos") + + simu_stub = grpc_stub.get_stub_insecure_channel( + target="localhost:" + str(config.get("SpeosServerPort")), + stub_type=simulation_pb2_grpc.SpeosSimulationStub, + ) + simu_load_req = simulation_pb2.Load_Request(guid=simu_create_res.guid, input_file_path=sv5_path) + simu_load_res = simu_stub.Load(simu_load_req) + + # Read simulation dm + simu_read_req = simulation_pb2.Read_Request(guid=simu_create_res.guid) + simu_read_res = simu_manager_stub.Read(simu_read_req) + assert len(simu_read_res.simulation.sensors) == 2 + assert simu_read_res.simulation.name == "Inverse.1" + + # Read simu template dm + simulation_templates_manager_stub = grpc_stub.get_stub_insecure_channel( + target="localhost:" + str(config.get("SpeosServerPort")), + stub_type=simulation_template_pb2_grpc.SimulationTemplatesManagerStub, + ) + simu_template_read_req = simulation_template_pb2.Read_Request(guid=simu_read_res.simulation.guid) + simu_template_read_res = simulation_templates_manager_stub.Read(simu_template_read_req) + assert simu_template_read_res.simulation_template.HasField("inverse_mc_simulation_template") + assert simu_template_read_res.simulation_template.inverse_mc_simulation_template.splitting == False + + # Duplicate the simulation template to have same but with splitting activated + simu_template_read_res.simulation_template.inverse_mc_simulation_template.splitting = True + simu_template_read_res.simulation_template.name = "Inverse.2" + simu_template_read_res.simulation_template.description = "Inverse simu with splitting" + + simu_template_create_req = simulation_template_pb2.Create_Request( + simulation_template=simu_template_read_res.simulation_template + ) + simu_template_create_res = simulation_templates_manager_stub.Create(simu_template_create_req) + + # Update the simulation to use new template (with splitting) -> ERROR + simu_read_res.simulation.guid = simu_template_create_res.guid + simu_update_req = simulation_pb2.Update_Request(guid=simu_create_res.guid, simulation=simu_read_res.simulation) + with pytest.raises(grpc.RpcError) as exc_info: + simu_update_res = simu_manager_stub.Update(simu_update_req) + error_details = json.loads(exc_info.value.details()) + assert error_details["ErrorName"] == "OPTCAALPAWithSplitting" + + # Create Job from simu guid + choose type + simu properties + job_manager_stub = grpc_stub.get_stub_insecure_channel( + target="localhost:" + str(config.get("SpeosServerPort")), + stub_type=job_pb2_grpc.SpeosJobsManagerStub, + ) + + j = job_pb2.Job() + j.simu_guid = simu_create_res.guid + j.job_type = job_pb2.Job_Type.CPU + # No optimized propagation and set related stop condition + j.inverse_mc_simulation_properties.optimized_propagation_none.stop_condition_passes_number = 3 + j.inverse_mc_simulation_properties.stop_condition_duration = 6 # Set stop condition on duration also + j.inverse_mc_simulation_properties.automatic_save_frequency = 600 # Set automatic save frequency + + job_create_req = job_pb2.Create_Request(job=j) + job_create_res = job_manager_stub.Create(job_create_req) + + # Start the job + job_stub = grpc_stub.get_stub_insecure_channel( + target="localhost:" + str(config.get("SpeosServerPort")), + stub_type=job_pb2_grpc.SpeosJobStub, + ) + job_start_req = job_pb2.Start_Request(guid=job_create_res.guid) + job_start_res = job_stub.Start(job_start_req) + + # Check job state every second + get_state_req = job_pb2.GetState_Request(guid=job_create_res.guid) + job_state_res = job_stub.GetState(get_state_req) + while ( + job_state_res.state != job_pb2.Job_State.FINISHED + and job_state_res.state != job_pb2.Job_State.STOPPED + and job_state_res.state != job_pb2.Job_State.IN_ERROR + ): + time.sleep(2) + + job_state_res = job_stub.GetState(get_state_req) + + # Get results + get_results_req = job_pb2.GetResults_Request(guid=job_create_res.guid) + get_results_res = job_stub.GetResults(get_results_req) + assert len(get_results_res.results) == 9 + + # Delete job + delete_res = job_manager_stub.Delete(job_pb2.Delete_Request(guid=job_create_res.guid)) + + # Delete simu + helper.remove_file(os.path.join(sv5_path, "CameraSensitivityBlue_1044-9741-9c42-85c2.spectrum")) + helper.remove_file(os.path.join(sv5_path, "CameraSensitivityGreen_b5d3-6c51-134d-a5d6.spectrum")) + helper.remove_file(os.path.join(sv5_path, "CameraSensitivityRed_9433-b5a9-12ab-7c7f.spectrum")) + helper.remove_file(os.path.join(sv5_path, "CameraTransmittance_7345-0c60-5ae6-d225.spectrum")) + delete_res = simu_manager_stub.Delete(simulation_pb2.Delete_Request(guid=simu_create_res.guid)) + + # Delete all simu templates + simu_templates_list_res = simulation_templates_manager_stub.List(simulation_template_pb2.List_Request()) + for simu_template_guid in simu_templates_list_res.guids: + delete_res = simulation_templates_manager_stub.Delete( + simulation_template_pb2.Delete_Request(guid=simu_template_guid) + ) + + # Delete all sensor templates + import ansys.api.speos.sensor.v1.sensor_pb2 as sensor_v1 + import ansys.api.speos.sensor.v1.sensor_pb2_grpc + + sensor_templates_manager_stub = grpc_stub.get_stub_insecure_channel( + target="localhost:" + str(config.get("SpeosServerPort")), + stub_type=ansys.api.speos.sensor.v1.sensor_pb2_grpc.SensorTemplatesManagerStub, + ) + sensor_templates_list_res = sensor_templates_manager_stub.List(sensor_v1.List_Request()) + for sensor_template_guid in sensor_templates_list_res.guids: + delete_res = sensor_templates_manager_stub.Delete(sensor_v1.Delete_Request(guid=sensor_template_guid))