106 lines
3.2 KiB
Python
106 lines
3.2 KiB
Python
|
|
from dataclasses import dataclass, field
|
||
|
|
from typing import List, Dict
|
||
|
|
import json
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass
|
||
|
|
class ExposureProfile:
|
||
|
|
"""Профиль выдержки для определённого ISO"""
|
||
|
|
iso: int
|
||
|
|
exposure_seconds: int
|
||
|
|
dark_count: int = 20
|
||
|
|
flat_count: int = 30
|
||
|
|
bias_count: int = 50
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass
|
||
|
|
class LensProfile:
|
||
|
|
"""Профиль объектива"""
|
||
|
|
name: str
|
||
|
|
aperture: str # например "f/2.8"
|
||
|
|
flat_duration_minutes: int = 10 # когда снимать Flat (рассвет/закат)
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass
|
||
|
|
class CameraProfile:
|
||
|
|
"""Профиль камеры"""
|
||
|
|
name: str # "Canon EOS 600D"
|
||
|
|
sensor_type: str = "APS-C" # APS-C, Full Frame
|
||
|
|
pixel_size_um: float = 4.3
|
||
|
|
read_noise_e: float = 2.5
|
||
|
|
|
||
|
|
# Настройки по умолчанию
|
||
|
|
default_iso: int = 800
|
||
|
|
default_exposure: int = 120
|
||
|
|
|
||
|
|
# Профили выдержек
|
||
|
|
exposures: List[ExposureProfile] = field(default_factory=list)
|
||
|
|
|
||
|
|
# Объективы
|
||
|
|
lenses: List[LensProfile] = field(default_factory=list)
|
||
|
|
|
||
|
|
def save(self, config_service):
|
||
|
|
"""Сохраняет профиль в конфиг"""
|
||
|
|
config_service.save_camera_profile(self)
|
||
|
|
|
||
|
|
def to_dict(self) -> dict:
|
||
|
|
return {
|
||
|
|
'name': self.name,
|
||
|
|
'sensor_type': self.sensor_type,
|
||
|
|
'pixel_size_um': self.pixel_size_um,
|
||
|
|
'read_noise_e': self.read_noise_e,
|
||
|
|
'default_iso': self.default_iso,
|
||
|
|
'default_exposure': self.default_exposure,
|
||
|
|
'exposures': [
|
||
|
|
{
|
||
|
|
'iso': e.iso,
|
||
|
|
'exposure_seconds': e.exposure_seconds,
|
||
|
|
'dark_count': e.dark_count,
|
||
|
|
'flat_count': e.flat_count,
|
||
|
|
'bias_count': e.bias_count
|
||
|
|
}
|
||
|
|
for e in self.exposures
|
||
|
|
],
|
||
|
|
'lenses': [
|
||
|
|
{
|
||
|
|
'name': l.name,
|
||
|
|
'aperture': l.aperture,
|
||
|
|
'flat_duration_minutes': l.flat_duration_minutes
|
||
|
|
}
|
||
|
|
for l in self.lenses
|
||
|
|
]
|
||
|
|
}
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def from_dict(cls, data: dict) -> 'CameraProfile':
|
||
|
|
exposures = [
|
||
|
|
ExposureProfile(
|
||
|
|
iso=e['iso'],
|
||
|
|
exposure_seconds=e['exposure_seconds'],
|
||
|
|
dark_count=e.get('dark_count', 20),
|
||
|
|
flat_count=e.get('flat_count', 30),
|
||
|
|
bias_count=e.get('bias_count', 50)
|
||
|
|
)
|
||
|
|
for e in data.get('exposures', [])
|
||
|
|
]
|
||
|
|
|
||
|
|
lenses = [
|
||
|
|
LensProfile(
|
||
|
|
name=l['name'],
|
||
|
|
aperture=l['aperture'],
|
||
|
|
flat_duration_minutes=l.get('flat_duration_minutes', 10)
|
||
|
|
)
|
||
|
|
for l in data.get('lenses', [])
|
||
|
|
]
|
||
|
|
|
||
|
|
return cls(
|
||
|
|
name=data['name'],
|
||
|
|
sensor_type=data.get('sensor_type', 'APS-C'),
|
||
|
|
pixel_size_um=data.get('pixel_size_um', 4.3),
|
||
|
|
read_noise_e=data.get('read_noise_e', 2.5),
|
||
|
|
default_iso=data.get('default_iso', 800),
|
||
|
|
default_exposure=data.get('default_exposure', 120),
|
||
|
|
exposures=exposures,
|
||
|
|
lenses=lenses
|
||
|
|
)
|