fix: Unit conversion of LazyValueRange.
The unit conversion was indeed botched, with a typo causing the start of the range to be converted as if it were the end of the range. Closes #3.main
parent
3a53e4ce46
commit
3c00530524
7
TODO.md
7
TODO.md
|
@ -510,7 +510,7 @@ Header color style can't be done, unfortunately. Body color feels unclean, so no
|
|||
|
||||
## BLCache
|
||||
- [ ] Replace every raw property with `BLField`.
|
||||
- [ ] Add matrix property support: https://developer.blender.org/docs/release_notes/3.0/python_api/#other-additions
|
||||
- [x] Add matrix property support: https://developer.blender.org/docs/release_notes/3.0/python_api/#other-additions
|
||||
- [ ] Fix many problems by persisting `_enum_cb_cache` and `_str_cb_cache`.
|
||||
- [ ] Docstring parser for descriptions.
|
||||
- [ ] Method of dynamically setting property options after creation, using `idproperty_ui_data`
|
||||
|
@ -524,6 +524,10 @@ We're trying to do our part by reporting bugs we find!
|
|||
This is where we keep track of them for now, if they're not covered by the above listings.
|
||||
|
||||
## Blender Maxwell Bugs
|
||||
See Issues.
|
||||
|
||||
## Testing
|
||||
- [ ] `pytest` integration exhibits a bootstrapping problem when using https://github.com/mondeja/pytest-blender
|
||||
|
||||
## Blender Bugs
|
||||
Reported:
|
||||
|
@ -545,6 +549,7 @@ Unreported:
|
|||
## Tidy3D bugs
|
||||
Unreported:
|
||||
- Directly running `SimulationTask.get()` is missing fields - it doesn't return some fields, including `created_at`. Listing tasks by folder is not broken.
|
||||
- Frequency ranges don't check for repeated elements.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ managed = true
|
|||
virtual = true
|
||||
dev-dependencies = [
|
||||
"ruff>=0.3.2",
|
||||
"fake-bpy-module-4-0>=20231118", ## TODO: Update to Blender 4.1.0
|
||||
"fake-bpy-module-4-0>=20231118",
|
||||
## TODO: Update to Blender 4.1.0
|
||||
]
|
||||
|
||||
[tool.rye.scripts]
|
||||
|
@ -143,3 +144,9 @@ max-args = 6
|
|||
quote-style = "single"
|
||||
indent-style = "tab"
|
||||
docstring-code-format = false
|
||||
|
||||
####################
|
||||
# - Tooling: Pytest
|
||||
####################
|
||||
#[tool.pytest.ini_options]
|
||||
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
from .array import ArrayFlow
|
||||
from .capabiltiies import CapabilitiesFlow
|
||||
from .capabilities import CapabilitiesFlow
|
||||
from .flow_kinds import FlowKind
|
||||
from .lazy_array_range import LazyArrayRange
|
||||
from .lazy_value_func import LazyValueFunc
|
||||
from .params import Params
|
||||
from .info import InfoFlow
|
||||
from .lazy_array_range import LazyArrayRangeFlow
|
||||
from .lazy_value_func import LazyValueFuncFlow
|
||||
from .params import ParamsFlow
|
||||
from .value import ValueFlow
|
||||
|
||||
__all__ = [
|
||||
'ArrayFlow',
|
||||
'CapabilitiesFlow',
|
||||
'FlowKind',
|
||||
'LazyArrayRange',
|
||||
'LazyValueFunc',
|
||||
'Params',
|
||||
'InfoFlow',
|
||||
'LazyArrayRangeFlow',
|
||||
'LazyValueFuncFlow',
|
||||
'ParamsFlow',
|
||||
'ValueFlow',
|
||||
]
|
||||
|
|
|
@ -50,19 +50,21 @@ class FlowKind(enum.StrEnum):
|
|||
def scale_to_unit_system(
|
||||
cls,
|
||||
kind: typ.Self,
|
||||
value,
|
||||
flow_obj,
|
||||
unit_system: spux.UnitSystem,
|
||||
):
|
||||
if kind == cls.Value:
|
||||
log.debug('%s: Scaling "%s" to Unit System', kind, str(flow_obj))
|
||||
if kind == FlowKind.Value:
|
||||
return spux.scale_to_unit_system(
|
||||
value,
|
||||
flow_obj,
|
||||
unit_system,
|
||||
)
|
||||
if kind == cls.LazyArrayRange:
|
||||
return value.rescale_to_unit_system(unit_system)
|
||||
if kind == FlowKind.LazyArrayRange:
|
||||
log.debug([kind, flow_obj, unit_system])
|
||||
return flow_obj.rescale_to_unit_system(unit_system)
|
||||
|
||||
if kind == cls.Params:
|
||||
return value.rescale_to_unit_system(unit_system)
|
||||
if kind == FlowKind.Params:
|
||||
return flow_obj.rescale_to_unit_system(unit_system)
|
||||
|
||||
msg = 'Tried to scale unknown kind'
|
||||
raise ValueError(msg)
|
||||
|
|
|
@ -8,11 +8,14 @@ import jaxtyping as jtyp
|
|||
import sympy as sp
|
||||
|
||||
from blender_maxwell.utils import extra_sympy_units as spux
|
||||
from blender_maxwell.utils import logger
|
||||
|
||||
from .array import ArrayFlow
|
||||
from .flow_kinds import FlowKind
|
||||
from .lazy_value_func import LazyValueFuncFlow
|
||||
|
||||
log = logger.get(__name__)
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True, kw_only=True)
|
||||
class LazyArrayRangeFlow:
|
||||
|
@ -84,6 +87,16 @@ class LazyArrayRangeFlow:
|
|||
|
||||
@functools.cached_property
|
||||
def mathtype(self) -> spux.MathType:
|
||||
"""Conservatively compute the most stringent `spux.MathType` that can represent both `self.start` and `self.stop`.
|
||||
|
||||
Notes:
|
||||
The mathtype is determined from start/stop either using `sympy` assumptions, or as Python types.
|
||||
|
||||
For precise information on how start/stop are "combined", see `spux.MathType.combine()`.
|
||||
|
||||
Returns:
|
||||
All symbols valid for use in the expression.
|
||||
"""
|
||||
# Get Start Mathtype
|
||||
if isinstance(self.start, spux.SympyType):
|
||||
start_mathtype = spux.MathType.from_expr(self.start)
|
||||
|
@ -97,12 +110,22 @@ class LazyArrayRangeFlow:
|
|||
stop_mathtype = spux.MathType.from_pytype(type(self.stop))
|
||||
|
||||
# Check Equal
|
||||
if start_mathtype != stop_mathtype:
|
||||
return spux.MathType.combine(start_mathtype, stop_mathtype)
|
||||
|
||||
return start_mathtype
|
||||
combined_mathtype = spux.MathType.combine(start_mathtype, stop_mathtype)
|
||||
log.debug(
|
||||
'%s: Computed MathType as %s (start_mathtype=%s, stop_mathtype=%s)',
|
||||
self,
|
||||
combined_mathtype,
|
||||
start_mathtype,
|
||||
stop_mathtype,
|
||||
)
|
||||
return combined_mathtype
|
||||
|
||||
def __len__(self):
|
||||
"""Compute the length of the array to be realized.
|
||||
|
||||
Returns:
|
||||
The number of steps.
|
||||
"""
|
||||
return self.steps
|
||||
|
||||
####################
|
||||
|
@ -121,6 +144,11 @@ class LazyArrayRangeFlow:
|
|||
ValueError: If the existing unit is `None`, indicating that there is no unit to correct.
|
||||
"""
|
||||
if self.unit is not None:
|
||||
log.debug(
|
||||
'%s: Corrected unit to %s',
|
||||
self,
|
||||
corrected_unit,
|
||||
)
|
||||
return LazyArrayRangeFlow(
|
||||
start=self.start,
|
||||
stop=self.stop,
|
||||
|
@ -146,6 +174,11 @@ class LazyArrayRangeFlow:
|
|||
ValueError: If the existing unit is `None`, indicating that there is no unit to correct.
|
||||
"""
|
||||
if self.unit is not None:
|
||||
log.debug(
|
||||
'%s: Scaled to unit %s',
|
||||
self,
|
||||
unit,
|
||||
)
|
||||
return LazyArrayRangeFlow(
|
||||
start=spux.scale_to_unit(self.start * self.unit, unit),
|
||||
stop=spux.scale_to_unit(self.stop * self.unit, unit),
|
||||
|
@ -171,13 +204,18 @@ class LazyArrayRangeFlow:
|
|||
ValueError: If the existing unit is `None`, indicating that there is no unit to correct.
|
||||
"""
|
||||
if self.unit is not None:
|
||||
log.debug(
|
||||
'%s: Scaled to unit system: %s',
|
||||
self,
|
||||
str(unit_system),
|
||||
)
|
||||
return LazyArrayRangeFlow(
|
||||
start=spux.strip_unit_system(
|
||||
spux.convert_to_unit_system(self.start * self.unit, unit_system),
|
||||
unit_system,
|
||||
),
|
||||
stop=spux.strip_unit_system(
|
||||
spux.convert_to_unit_system(self.start * self.unit, unit_system),
|
||||
spux.convert_to_unit_system(self.stop * self.unit, unit_system),
|
||||
unit_system,
|
||||
),
|
||||
steps=self.steps,
|
||||
|
|
|
@ -320,7 +320,7 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
|||
def on_sim_changed(self, props) -> None:
|
||||
# Sim Linked | First Value Change
|
||||
if self.inputs['Sim'].is_linked and not props['sim_info_available']:
|
||||
log.critical('First Change: Mark Sim Info Available')
|
||||
log.debug('%s: First Change; Mark Sim Info Available', self.sim_node_name)
|
||||
self.sim = bl_cache.Signal.InvalidateCache
|
||||
self.total_monitor_data = bl_cache.Signal.InvalidateCache
|
||||
self.is_sim_uploadable = bl_cache.Signal.InvalidateCache
|
||||
|
@ -332,7 +332,7 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
|||
and props['sim_info_available']
|
||||
and not props['sim_info_invalidated']
|
||||
):
|
||||
log.critical('Second Change: Mark Sim Info Invalided')
|
||||
log.debug('%s: Second Change; Mark Sim Info Invalided', self.sim_node_name)
|
||||
self.sim_info_invalidated = True
|
||||
|
||||
# Sim Linked | Nth Time
|
||||
|
@ -346,7 +346,9 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
|||
## -> Luckily, since we know there's no sim, invalidation is cheap.
|
||||
## -> Ends up being a "circuit breaker" for sim_info_invalidated.
|
||||
elif not self.inputs['Sim'].is_linked:
|
||||
log.critical('Unlinked: Short Circuit Zap Cache')
|
||||
log.debug(
|
||||
'%s: Unlinked; Short Circuit the Sim Info Cache', self.sim_node_name
|
||||
)
|
||||
self.sim = bl_cache.Signal.InvalidateCache
|
||||
self.total_monitor_data = bl_cache.Signal.InvalidateCache
|
||||
self.is_sim_uploadable = bl_cache.Signal.InvalidateCache
|
||||
|
@ -368,7 +370,7 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
|||
props={'uploaded_task_id'},
|
||||
)
|
||||
def on_uploaded_task_changed(self, props):
|
||||
log.critical('Uploaded Task Changed')
|
||||
log.debug('Uploaded Task Changed')
|
||||
self.is_sim_uploadable = bl_cache.Signal.InvalidateCache
|
||||
|
||||
if props['uploaded_task_id'] != '':
|
||||
|
|
|
@ -49,15 +49,19 @@ def set_offline():
|
|||
|
||||
def check_online() -> bool:
|
||||
global IS_ONLINE # noqa: PLW0603
|
||||
log.info('Checking Internet Connection...')
|
||||
|
||||
try:
|
||||
urllib.request.urlopen(
|
||||
'https://docs.flexcompute.com/projects/tidy3d/en/latest/index.html',
|
||||
timeout=2,
|
||||
)
|
||||
except:
|
||||
except: # noqa: E722
|
||||
log.info('Internet is currently offline')
|
||||
IS_ONLINE = False
|
||||
return False
|
||||
else:
|
||||
log.info('Internet connection is working')
|
||||
IS_ONLINE = True
|
||||
return True
|
||||
|
||||
|
@ -67,26 +71,25 @@ def check_online() -> bool:
|
|||
####################
|
||||
def check_authentication() -> bool:
|
||||
global IS_AUTHENTICATED # noqa: PLW0603
|
||||
log.critical('Checking Authentication')
|
||||
|
||||
# Check Previous Authentication
|
||||
## If we authenticated once, we presume that it'll work again.
|
||||
## TODO: API keys can change... It would just look like "offline" for now.
|
||||
if IS_AUTHENTICATED:
|
||||
return True
|
||||
log.info('Checking Tidy3D Authentication...')
|
||||
|
||||
api_key = td_web.core.http_util.api_key()
|
||||
if api_key is not None:
|
||||
log.info('Found stored Tidy3D API key')
|
||||
try:
|
||||
td_web.test()
|
||||
set_online()
|
||||
except td.exceptions.WebError:
|
||||
set_offline()
|
||||
log.info('Authenticated to Tidy3D cloud')
|
||||
return False
|
||||
else:
|
||||
set_online()
|
||||
log.info('Authenticated to Tidy3D cloud')
|
||||
|
||||
IS_AUTHENTICATED = True
|
||||
return True
|
||||
|
||||
log.info('Tidy3D API key is missing')
|
||||
return False
|
||||
|
||||
|
||||
|
@ -99,6 +102,7 @@ TD_CONFIG = Path(td_web.cli.constants.CONFIG_FILE)
|
|||
|
||||
## TODO: Robustness is key - internet might be down.
|
||||
## -> I'm not a huge fan of the max 2sec startup time burden
|
||||
## -> I also don't love "calling" Tidy3D on startup, privacy-wise
|
||||
if TD_CONFIG.is_file() and check_online():
|
||||
check_authentication()
|
||||
|
||||
|
|
|
@ -83,7 +83,6 @@ if __name__ == '__main__':
|
|||
|
||||
# Run Addon
|
||||
print(f'Blender: Running "{info.ADDON_NAME}"...')
|
||||
subprocess.run
|
||||
return_code, output = run_blender(
|
||||
None, headless=False, load_devfile=True, monitor=True
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue