Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions dosview/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,11 @@ def initUI(self):
self.upload_file_button.setMaximumHeight(20)
self.upload_file_button.clicked.connect(lambda: UploadFileDialog().exec_())

self.export_csv_button = QPushButton("Export spectrum")
self.export_csv_button.setMaximumHeight(20)
self.export_csv_button.clicked.connect(self.export_spectrum_csv)
self.export_csv_button.setEnabled(False)

log_view_widget = QWidget()

self.left_panel = QSplitter(Qt.Vertical)
Expand All @@ -814,6 +819,7 @@ def initUI(self):
vb = QHBoxLayout()
vb.addWidget(self.open_img_view_button)
vb.addWidget(self.upload_file_button)
vb.addWidget(self.export_csv_button)
self.left_panel.setLayout(vb)

self.logView_splitter = QSplitter(Qt.Horizontal)
Expand Down Expand Up @@ -843,8 +849,9 @@ def start_data_loading(self):
self.load_data_thread.start()

def on_data_loaded(self, data):
self.data = data # TODO>.. tohle do budoucna zrusit a nahradit tridou parseru..
self.data = data # TODO>.. tohle do budoucna zrusit a nahradit tridou parseru..
print("Data are fully loaded...")
self.export_csv_button.setEnabled(True)
self.plot_canvas.plot(data)
print("After plot data canvas")

Expand Down Expand Up @@ -888,12 +895,28 @@ def add_properties_to_tree(item, properties):


def open_spectrogram_view(self):
matrix = self.data[-1] #TODO .. tohle predelat na nejakou tridu pro parserovani
matrix = self.data[-1] #TODO .. tohle predelat na nejakou tridu pro parserovani

w = DataSpectrumView(self)
w.show()
w.plot_data(matrix)

def export_spectrum_csv(self):
path, _ = QFileDialog.getSaveFileName(
self, "Export spectrum", "", "CSV files (*.csv)"
)
if not path:
return
if not path.endswith(".csv"):
path += ".csv"
import csv
hist = self.data[2]
with open(path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["channel", "counts"])
for ch, cnt in enumerate(hist):
writer.writerow([ch, int(cnt)])


class UploadFileDialog(QDialog):
def __init__(self, parent=None):
Expand Down
30 changes: 20 additions & 10 deletions dosview/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,43 @@ def parse(self): # pragma: no cover - concrete classes implement
raise NotImplementedError


class Airdos04CLogParser(BaseLogParser):
"""Parser for AIRDOS04C log files."""
class AirdosV2LogParser(BaseLogParser):
"""Parser for AIRDOS log files using data format version 2.x."""

@staticmethod
def detect(file_path: str | Path) -> bool:
with open(file_path, "r") as f:
for line in f:
if line.startswith("$DOS") and "AIRDOS04C" in line:
return True
if line.startswith("$DOS"):
parts = line.strip().split(",")
# parts[2] = fw-version; MAJOR.MINOR encodes the data format version
if len(parts) > 2 and parts[2].startswith("2."):
return True
return False

def parse(self):
start_time = time.time()
print("AIRDOS04C parser start")
print("AIRDOS v2 parser start")
metadata = {
"log_runs_count": 0,
"log_device_info": {},
"log_info": {},
}
hist = np.zeros(1024, dtype=int)
hist = np.zeros(65536, dtype=int)
total_counts = 0
sums: List[int] = []
time_axis: List[float] = []
inside_run = False
current_hist = None
current_counts = 0
device_type = "unknown"

with open(self.file_path, "r") as file:
for line in file:
parts = line.strip().split(",")
match parts[0]:
case "$DOS":
device_type = parts[1] if len(parts) > 1 else "unknown"
metadata["log_device_info"]["DOS"] = {
"type": parts[0],
"hw-model": parts[1],
Expand Down Expand Up @@ -102,12 +107,16 @@ def parse(self):
metadata["log_info"]["events_total"] = int(total_counts)
metadata["log_info"]["log_type_version"] = "2.0"
metadata["log_info"]["log_type"] = "xDOS_SPECTRAL"
metadata["log_info"]["detector_type"] = "AIRDOS04C"
print("Parsed AIRDOS04C format in", time.time() - start_time, "s")
metadata["log_info"]["detector_type"] = device_type
print("Parsed AIRDOS v2 format in", time.time() - start_time, "s")

return [np.array(time_axis), np.array(sums), hist, metadata]


# Backwards-compatible alias
Airdos04CLogParser = AirdosV2LogParser


class OldLogParser(BaseLogParser):
"""Parser for legacy (pre-AIRDOS04C) log files."""

Expand Down Expand Up @@ -203,7 +212,7 @@ def parse(self):
return [time_column, sums, hist, metadata]


LOG_PARSERS: Sequence[type[BaseLogParser]] = [Airdos04CLogParser, OldLogParser]
LOG_PARSERS: Sequence[type[BaseLogParser]] = [AirdosV2LogParser, OldLogParser]


def get_parser_for_file(file_path: str | Path) -> BaseLogParser:
Expand All @@ -220,7 +229,8 @@ def parse_file(file_path: str | Path):

__all__ = [
"BaseLogParser",
"Airdos04CLogParser",
"AirdosV2LogParser",
"Airdos04CLogParser", # backwards-compatible alias
"OldLogParser",
"get_parser_for_file",
"parse_file",
Expand Down
Loading