| 
48 | 48 |     }  | 
49 | 49 | }  | 
50 | 50 | 
 
  | 
 | 51 | +AERO_MODE_CTOR_SAMPLED = {  | 
 | 52 | +    "test_mode": {  | 
 | 53 | +        "mass_frac": [{"H2O": [1]}],  | 
 | 54 | +        "diam_type": "geometric",  | 
 | 55 | +        "mode_type": "sampled",  | 
 | 56 | +        "size_dist": [  | 
 | 57 | +            {"diam": [1, 2, 3, 4]},  | 
 | 58 | +            {"num_conc": [100, 200, 300]},  | 
 | 59 | +        ],  | 
 | 60 | +    }  | 
 | 61 | +}  | 
 | 62 | + | 
51 | 63 | 
 
  | 
52 | 64 | class TestAeroMode:  | 
53 | 65 |     @staticmethod  | 
@@ -289,3 +301,127 @@ def test_segfault_case():  # TODO #319  | 
289 | 301 |         )  | 
290 | 302 |         print(fishy_ctor_arg)  | 
291 | 303 |         ppmc.AeroMode(aero_data, fishy_ctor_arg)  | 
 | 304 | + | 
 | 305 | +    @staticmethod  | 
 | 306 | +    @pytest.mark.skipif(platform.machine() == "arm64", reason="TODO #348")  | 
 | 307 | +    def test_sampled_without_size_dist():  | 
 | 308 | +        # arrange  | 
 | 309 | +        aero_data = ppmc.AeroData(AERO_DATA_CTOR_ARG_MINIMAL)  | 
 | 310 | +        fishy_ctor_arg = copy.deepcopy(AERO_MODE_CTOR_LOG_NORMAL)  | 
 | 311 | +        fishy_ctor_arg["test_mode"]["mode_type"] = "sampled"  | 
 | 312 | + | 
 | 313 | +        # act  | 
 | 314 | +        with pytest.raises(Exception) as exc_info:  | 
 | 315 | +            ppmc.AeroMode(aero_data, fishy_ctor_arg)  | 
 | 316 | + | 
 | 317 | +        # assert  | 
 | 318 | +        assert str(exc_info.value) == "size_dist key must be set for mode_type=sampled"  | 
 | 319 | + | 
 | 320 | +    @staticmethod  | 
 | 321 | +    @pytest.mark.parametrize(  | 
 | 322 | +        "fishy",  | 
 | 323 | +        (  | 
 | 324 | +            None,  | 
 | 325 | +            [],  | 
 | 326 | +            [{}, {}, {}],  | 
 | 327 | +            [{}, []],  | 
 | 328 | +            [{"diam": None}, {}],  | 
 | 329 | +            [{"num_conc": None}, {}],  | 
 | 330 | +            [{"diam": None, "": None}, {}],  | 
 | 331 | +            [{"num_conc": None, "": None}, {}],  | 
 | 332 | +        ),  | 
 | 333 | +    )  | 
 | 334 | +    @pytest.mark.skipif(platform.machine() == "arm64", reason="TODO #348")  | 
 | 335 | +    def test_sampled_with_fishy_size_dist(fishy):  | 
 | 336 | +        # arrange  | 
 | 337 | +        aero_data = ppmc.AeroData(AERO_DATA_CTOR_ARG_MINIMAL)  | 
 | 338 | +        fishy_ctor_arg = copy.deepcopy(AERO_MODE_CTOR_LOG_NORMAL)  | 
 | 339 | +        fishy_ctor_arg["test_mode"]["mode_type"] = "sampled"  | 
 | 340 | +        fishy_ctor_arg["test_mode"]["size_dist"] = fishy  | 
 | 341 | + | 
 | 342 | +        # act  | 
 | 343 | +        with pytest.raises(Exception) as exc_info:  | 
 | 344 | +            ppmc.AeroMode(aero_data, fishy_ctor_arg)  | 
 | 345 | + | 
 | 346 | +        # assert  | 
 | 347 | +        assert (  | 
 | 348 | +            str(exc_info.value)  | 
 | 349 | +            == "size_dist value must be an iterable of two single-element dicts"  | 
 | 350 | +            + " (first with 'diam', second with 'num_conc' as keys)"  | 
 | 351 | +        )  | 
 | 352 | + | 
 | 353 | +    @staticmethod  | 
 | 354 | +    @pytest.mark.skipif(platform.machine() == "arm64", reason="TODO #348")  | 
 | 355 | +    def test_sampled_with_diam_of_different_len_than_num_conc():  | 
 | 356 | +        # arrange  | 
 | 357 | +        aero_data = ppmc.AeroData(AERO_DATA_CTOR_ARG_MINIMAL)  | 
 | 358 | +        fishy_ctor_arg = copy.deepcopy(AERO_MODE_CTOR_LOG_NORMAL)  | 
 | 359 | +        fishy_ctor_arg["test_mode"]["mode_type"] = "sampled"  | 
 | 360 | +        fishy_ctor_arg["test_mode"]["size_dist"] = [  | 
 | 361 | +            {"diam": [1, 2, 3]},  | 
 | 362 | +            {"num_conc": [1, 2, 3]},  | 
 | 363 | +        ]  | 
 | 364 | + | 
 | 365 | +        # act  | 
 | 366 | +        with pytest.raises(Exception) as exc_info:  | 
 | 367 | +            ppmc.AeroMode(aero_data, fishy_ctor_arg)  | 
 | 368 | + | 
 | 369 | +        # assert  | 
 | 370 | +        assert (  | 
 | 371 | +            str(exc_info.value)  | 
 | 372 | +            == "size_dist['num_conc'] must have len(size_dist['diam'])-1 elements"  | 
 | 373 | +        )  | 
 | 374 | + | 
 | 375 | +    @staticmethod  | 
 | 376 | +    def test_sampled():  | 
 | 377 | +        # arrange  | 
 | 378 | +        aero_data = ppmc.AeroData(AERO_DATA_CTOR_ARG_MINIMAL)  | 
 | 379 | + | 
 | 380 | +        # act  | 
 | 381 | +        sut = ppmc.AeroMode(aero_data, AERO_MODE_CTOR_SAMPLED)  | 
 | 382 | + | 
 | 383 | +        # assert  | 
 | 384 | +        assert sut.type == "sampled"  | 
 | 385 | +        assert sut.num_conc == np.sum(  | 
 | 386 | +            AERO_MODE_CTOR_SAMPLED["test_mode"]["size_dist"][1]["num_conc"]  | 
 | 387 | +        )  | 
 | 388 | +        assert (  | 
 | 389 | +            sut.sample_num_conc  | 
 | 390 | +            == AERO_MODE_CTOR_SAMPLED["test_mode"]["size_dist"][1]["num_conc"]  | 
 | 391 | +        )  | 
 | 392 | +        assert (  | 
 | 393 | +            np.array(sut.sample_radius) * 2  | 
 | 394 | +            == AERO_MODE_CTOR_SAMPLED["test_mode"]["size_dist"][0]["diam"]  | 
 | 395 | +        ).all()  | 
 | 396 | + | 
 | 397 | +    @staticmethod  | 
 | 398 | +    def test_set_sample():  | 
 | 399 | +        # arrange  | 
 | 400 | +        aero_data = ppmc.AeroData(AERO_DATA_CTOR_ARG_MINIMAL)  | 
 | 401 | + | 
 | 402 | +        diams = [1, 2, 3, 4]  | 
 | 403 | +        num_concs = [100, 200, 300]  | 
 | 404 | +        sut = ppmc.AeroMode(  | 
 | 405 | +            aero_data,  | 
 | 406 | +            {  | 
 | 407 | +                "test_mode": {  | 
 | 408 | +                    "mass_frac": [{"H2O": [1]}],  | 
 | 409 | +                    "diam_type": "geometric",  | 
 | 410 | +                    "mode_type": "sampled",  | 
 | 411 | +                    "size_dist": [  | 
 | 412 | +                        {"diam": diams},  | 
 | 413 | +                        {"num_conc": num_concs},  | 
 | 414 | +                    ],  | 
 | 415 | +                }  | 
 | 416 | +            },  | 
 | 417 | +        )  | 
 | 418 | +        num_conc_orig = sut.num_conc  | 
 | 419 | +        # act  | 
 | 420 | +        diams = [0.5 * x for x in diams]  | 
 | 421 | +        num_concs = [2 * x for x in num_concs]  | 
 | 422 | +        sut.set_sample(diams, num_concs)  | 
 | 423 | +        # assert  | 
 | 424 | +        assert sut.num_conc == np.sum(num_concs)  | 
 | 425 | +        assert sut.sample_num_conc == num_concs  | 
 | 426 | +        assert (np.array(sut.sample_radius) * 2 == diams).all()  | 
 | 427 | +        assert sut.num_conc == num_conc_orig * 2  | 
0 commit comments