Add example pipeline in C

This commit is contained in:
root
2023-04-06 10:41:04 +02:00
parent f90fc56858
commit b41f3193ab
21 changed files with 571 additions and 118 deletions
@@ -1,9 +1,9 @@
{
"camera_calibration": {
"reference_marker": [
352,
338,
502,
453,
441,
606
],
"reference_marker_width": 413.0,
@@ -25,6 +25,6 @@
"Bernina"
],
"alias": [
"CAMERA_BSSS (SARES20-CAMS142-M3)"
"SAMPLECAM_INLINE (SARES20-CAMS142-M3)"
]
}
@@ -0,0 +1,31 @@
{
"camera_calibration": {
"reference_marker": [
0,
0,
100,
100
],
"reference_marker_width": 100.0,
"reference_marker_height": 100.0,
"angle_horizontal": 0.0,
"angle_vertical": 0.0
},
"mirror_x": false,
"mirror_y": false,
"rotate": 0,
"roi": null,
"image_background": null,
"source_type": "bsread",
"prefix": "SATOP21-PMOS127-2D",
"source": "SATOP21-PMOS127-2D",
"name": "SATOP21-PMOS127-2D",
"connections": 2,
"buffer_size": 0,
"forwarder_port": [],
"group": [
"Photonics"
],
"alias": [],
"protocol": "tcp"
}
@@ -19,6 +19,7 @@
"SATES30-CAMS182-GIGE1": "SATES30-CAMS182-GIGE1",
"SATES30-CAMS182-GIGE2": "SATES30-CAMS182-GIGE2",
"SATES31-CAMS187-RIXS1": "SATES31-CAMS187-RIXS1",
"SATOP21-PMOS127-2D": "SATOP21-PMOS127-2D",
"SATOP31-PMOS132-2D": "SATOP31-PMOS132-2D",
"SINDI02-DSCR075": "SINDI02-DSCR075",
"SLAAR02-LPMO01-C321": "SLAAR02-LPMO01-C321",
+2 -1
View File
@@ -17,7 +17,8 @@
"expanding": false,
"instances": [
"SARFE10-PPRM064",
"SATOP31-PMOS132-2D"
"SATOP31-PMOS132-2D",
"SATOP21-PMOS127-2D"
]
},
"http://sf-daqsync-08.psi.ch:8880": {
@@ -11,10 +11,10 @@
"name": "SARES11-XMI125-C4P1_db",
"mode": "PUSH",
"roi_signal": [
100,
700,
550,
750
900,
500,
700
],
"no_client_timeout": 0,
"pixel_bkg": 0,
@@ -8,6 +8,10 @@
"pipeline_type": "processing",
"camera_name": "SARES20-PROF141-M1",
"name": "SARES20-PROF141-M1_proc",
"function": "bernina",
"mode": "PUSH"
}
"_function": "bernina",
"function": "test_pprm.py",
"create_header": "once",
"block": false,
"mode": "PUSH",
"reload": true
}
@@ -17,12 +17,12 @@
"down": "SARFE10-CVME-PHO6212:Lnk9Ch13-DATA-SUM",
"right": "SARFE10-CVME-PHO6212:Lnk9Ch14-DATA-SUM",
"left": "SARFE10-CVME-PHO6212:Lnk9Ch15-DATA-SUM",
"up_calib": 0.15959758776955815,
"down_calib": 0.17081416074661804,
"left_calib": 0.44737311355742443,
"right_calib": 0.2736612788911648,
"horiz_calib": -3.928214392529789,
"vert_calib": -7.346281801499673,
"up_calib": 0.29332902630344176,
"down_calib": 0.30758809127657744,
"left_calib": 0.8548507102577435,
"right_calib": 0.5254048353918549,
"horiz_calib": -3.9686377191422566,
"vert_calib": -6.757177531835748,
"uJ_calib": 834.5191797495979,
"threshold": 0,
"queue_length": 5000,
@@ -60,9 +60,9 @@
0.3
],
"calib_x_norm": [
0.07705425324290305,
0.000292090419390871,
-0.0756869008908959
0.07725444027758947,
-0.0008820870911578288,
-0.0739309393064352
],
"calib_y_range": [
-0.3,
@@ -70,20 +70,20 @@
0.3
],
"calib_y_norm": [
0.0405085485929619,
0.00025258183377802507,
-0.04116542147956046
0.044622126986971204,
-0.0008061137879948807,
-0.04417234336298802
],
"calib_time": "2022-11-28 16:19:37",
"calib_datetime": "2023-03-13 17:13:41",
"calib_datetime": "2023-03-20 14:25:54",
"calib_x_norm_std": [
0.06063214980948818,
0.06221414202235211,
0.06667909972355505
0.09961747340145947,
0.10733784051069324,
0.0929030520787079
],
"calib_y_norm_std": [
0.06069608759370142,
0.05655588611057008,
0.06231444141801817
0.09287619707647062,
0.092107183273319,
0.09302589672639311
]
}
@@ -19,12 +19,12 @@
"down": "SAROP11-CVME-PBPS2:Lnk9Ch11-DATA-SUM",
"right": "SAROP11-CVME-PBPS2:Lnk9Ch14-DATA-SUM",
"left": "SAROP11-CVME-PBPS2:Lnk9Ch15-DATA-SUM",
"up_calib": 4.176246646802521,
"down_calib": 5.0147722517321744,
"left_calib": 4.226868737030241,
"right_calib": 4.595144040785396,
"horiz_calib": -5.938292083354949,
"vert_calib": 5.750883131195752,
"up_calib": 0.6296855239312056,
"down_calib": 0.6822391000717031,
"left_calib": 0.4013112158986877,
"right_calib": 0.43663511455622184,
"horiz_calib": -4.489940533745727,
"vert_calib": 4.432874535470348,
"uJ_calib": 605.4608924473305,
"threshold": 0,
"queue_length": 5000,
@@ -62,9 +62,9 @@
0.3
],
"calib_x_norm": [
0.05144210467883525,
0.0006052215239522377,
-0.04959704792226395
0.06455376367074324,
-0.004423482191118885,
-0.06907829570520817
],
"calib_y_range": [
-0.3,
@@ -72,19 +72,19 @@
0.3
],
"calib_y_norm": [
-0.05168657093812036,
0.0007021663413024587,
0.05264523103248323
-0.06564181411065985,
-0.0008317809501211942,
0.06971053913078763
],
"calib_datetime": "2023-03-02 10:00:35",
"calib_datetime": "2023-03-20 14:28:15",
"calib_x_norm_std": [
0.594488273756939,
0.6069233875455338,
0.63112542665871
0.05738778249204604,
0.06125085163512557,
0.06392592319735892
],
"calib_y_norm_std": [
0.5810483125243515,
0.6050056030333926,
0.6023487356109991
0.07023632581683162,
0.07117317113274499,
0.08021938968881043
]
}
@@ -18,12 +18,12 @@
"down": "SAROP11-CVME-PBPS1:Lnk9Ch5-DATA-SUM",
"right": "SAROP11-CVME-PBPS1:Lnk9Ch3-DATA-SUM",
"left": "SAROP11-CVME-PBPS1:Lnk9Ch7-DATA-SUM",
"up_calib": 3.112906892007253,
"down_calib": 2.42031522941779,
"left_calib": 3.0712034522489846,
"right_calib": 2.6667721760426386,
"horiz_calib": -5.887206380557174,
"vert_calib": 5.859029430684977,
"up_calib": 4.856902438997528,
"down_calib": 3.6407001867683255,
"left_calib": 2.5431847379184935,
"right_calib": 2.258752231178428,
"horiz_calib": -4.923045366857815,
"vert_calib": 5.191012812577014,
"uJ_calib": 605.9512700123181,
"threshold": 0,
"queue_length": 1000,
@@ -66,14 +66,14 @@
0.3
],
"calib_x_norm": [
0.052679439786701664,
0.001497643249781178,
-0.04923647095519678
0.06097587138301983,
-0.0005498292535706359,
-0.06089990982331022
],
"calib_x_norm_std": [
0.6146987957054612,
0.6088117395208462,
0.5948902988515276
0.12938263783219212,
0.13160024776911167,
0.1278339097734837
],
"calib_y_range": [
-0.3,
@@ -81,15 +81,15 @@
0.3
],
"calib_y_norm": [
-0.050746643828704,
0.000785186946847148,
0.05165939578899666
-0.054567022258138184,
0.003407500099057587,
0.061017358220810655
],
"calib_y_norm_std": [
0.6016897603750389,
0.5789543559357142,
0.593537052066037
0.14051543884010068,
0.14684107677948718,
0.1415533936562058
],
"calib_datetime": "2023-03-02 10:03:18",
"calib_datetime": "2023-03-20 14:30:57",
"reload": true
}
@@ -3,16 +3,17 @@
"image_background": "SATBD02-DSCR050_20221013_123827_350915",
"image_threshold": null,
"image_region_of_interest": [
232,
1625,
534,
861
94,
1700,
521,
1145
],
"image_good_region": {
"threshold": 0.10000000000000003,
"gfscale": 10.0
"image_good_region": null,
"image_slices": {
"number_of_slices": 10,
"scale": 1.8,
"orientation": "horizontal"
},
"image_slices": null,
"pipeline_type": "processing",
"camera_name": "SATBD02-DSCR050",
"name": "SATBD02-DSCR050_sp",
@@ -0,0 +1,20 @@
{
"image_background_enable": false,
"image_background": "SATOP31-PMOS132-2D_20220607_121502_104208",
"image_threshold": null,
"image_region_of_interest": null,
"image_good_region": null,
"image_slices": null,
"pipeline_type": "processing",
"camera_name": "SATOP21-PMOS127-2D",
"name": "SATOP21-PMOS127-2D_pmos",
"function": "pmos132-2D.py",
"mode": "PUB",
"no_client_timeout": 0,
"reload": true,
"processing_threads": 6,
"thread_buffer_size": 30,
"abort_on_error": false,
"pixel_bkg": 1,
"port": "9001"
}
@@ -0,0 +1,11 @@
{
"image_background_enable": false,
"image_background": null,
"image_threshold": null,
"image_region_of_interest": null,
"image_good_region": null,
"image_slices": null,
"pipeline_type": "processing",
"camera_name": "SATOP21-PMOS127-2D",
"name": "SATOP21-PMOS127-2D_sp"
}
@@ -10,5 +10,6 @@
"name": "SLAAR02-LPMO02-C322_proc",
"function": "pprm_simple.py",
"mode": "PUSH",
"no_client_timeout": 0
"no_client_timeout": 0,
"reload": true
}
@@ -1,51 +1,19 @@
{
"#S10BC02-DSRM310_ib": "S10BC02-DSRM310_ib",
"#S10BC02-DSRM310_profiles": "S10BC02-DSRM310_profiles",
"#S10BD01-DSCR030_ib": "S10BD01-DSCR030_ib",
"#SARCL01-DSCR170_ib": "SARCL01-DSCR170_ib",
"#SARES11-SPEC125-M1_psen_db": "SARES11-SPEC125-M1_psen_db",
"#SARES11-SPEC125-M1_psen_ib": "SARES11-SPEC125-M1_psen_ib",
"#SARES11-SPEC125-M1_test": "SARES11-SPEC125-M1_test",
"#SARES11-SPEC125-M2_psen_db1": "SARES11-SPEC125-M2_psen_db",
"#SARES11-SPEC125-M2_psen_ib": "SARES11-SPEC125-M2_psen_ib",
"#SARES11-XMI125-C4P1_ib": "SARES11-XMI125-C4P1_ib",
"#SARES11-XPR125-C4P2_sp": "SARES11-XPR125-C4P2_sp",
"#SARES12-CAMS128-M1_psen_db": "SARES12-CAMS128-M1_psen_db",
"#SARES12-CAMS128-M1_psen_ib": "SARES12-CAMS128-M1_psen_ib",
"#SARES20-CAMS142-M1_psen_db": "SARES20-CAMS142-M1_psen_db",
"#SARES20-CAMS142-M1_psen_ib": "SARES20-CAMS142-M1_psen_ib",
"#SARES20-CAMS142-M3_ib": "SARES20-CAMS142-M3_ib",
"#SARES20-CAMS142-M5_psen_ib": "SARES20-CAMS142-M5_psen_ib",
"#SARES20-DSDPPRM_ib": "SARES20-DSDPPRM_ib",
"#SARES20-DSDPPRM_proc": "SARES20-DSDPPRM_proc",
"#SARES20-PROF141-M1_ib": "SARES20-PROF141-M1_ib",
"#SARES20-PROF141-M1_proc": "SARES20-PROF141-M1_proc",
"#SARES30-CAMS156-PCO1_ib": "SARES30-CAMS156-PCO1_ib",
"#SARES30-CAMS156-XE_ib": "SARES30-CAMS156-XE_ib",
"#SARFE10-PPRM064_ib": "SARFE10-PPRM064_ib",
"#SARFE10-PSSS059_store": "SARFE10-PSSS059_store",
"#SAROP11-ATT01_proc": "SAROP11-ATT01_proc",
"#SAROP21-PPRM102_ib": "SAROP21-PPRM102_ib",
"#SAROP21-PPRM102_proc": "SAROP21-PPRM102_proc",
"#SAROP21-PPRM113_proc": "SAROP21-PPRM113_proc",
"#SAROP21-PPRM138_ib": "SAROP21-PPRM138_ib",
"#SAROP31-PPRM113_ib": "SAROP31-PPRM113_ib",
"#SAROP31-PPRM150_ib": "SAROP31-PPRM150_ib",
"#SATBD02-DSCR050_ib": "SATBD02-DSCR050_ib",
"#SATES21-CAMS-PATT1_spec_ib": "SATES21-CAMS-PATT1_spec_ib",
"#SATES21-CAMS154-M1_spec_ib": "SATES21-CAMS154-M1_spec_ib",
"#SATES24-CAMS161-M1_spec_ib": "SATES24-CAMS161-M1_spec_ib",
"#SATES30-CAMS182-GIGE1_ib": "SATES30-CAMS182-GIGE1_ib",
"#SATES30-CAMS182-GIGE2_ib": "SATES30-CAMS182-GIGE2_ib",
"#SATES31-CAMS187-RIXS1_ib": "SATES31-CAMS187-RIXS1_ib",
"#SATOP31-PMOS132-2D_store": "SATOP31-PMOS132-2D_store",
"#SINBC02-DSRM310_ib": "SINBC02-DSRM310_ib",
"#SINBC02-DSRM310_profiles": "SINBC02-DSRM310_profiles",
"#SINDI02-DSCR075_ib": "SINDI02-DSCR075_ib",
"#jungfrau_proc": "jungfrau_proc",
"#test_furka": "test_furka",
"#test_merge": "test_merge",
"#test_proc_with_bs": "test_proc_with_bs",
"#test_str": "test_str",
"#test_stream": "test_stream",
"#test_tadej": "test_tadej",
"#testdb_ib": "testdb_ib",
@@ -55,6 +23,7 @@
"SARES20-CAMS142-M3_proc": "SARES20-CAMS142-M3_proc",
"SARES20-CAMS142-M5_psen_db": "SARES20-CAMS142-M5_psen_db",
"SARES20-CAMS142-M5_psen_db_proxy": "SARES20-CAMS142-M5_psen_db_proxy",
"SARES20-PROF141-M1_proc": "SARES20-PROF141-M1_proc",
"SARES30-CAMS156-XE_proc": "SARES30-CAMS156-XE_proc",
"SARFE10-PBPS053_proc": "SARFE10-PBPS053_proc",
"SARFE10-PPRM064_proc": "SARFE10-PPRM064_proc",
@@ -79,6 +48,7 @@
"SATES30-CAMS182-GIGE1_profiles": "SATES30-CAMS182-GIGE1_profiles",
"SATES30-CAMS182-GIGE2_profiles": "SATES30-CAMS182-GIGE2_profiles",
"SATES31-CAMS187-RIXS1_proc": "SATES31-CAMS187-RIXS1_proc",
"SATOP21-PMOS127-2D_pmos": "SATOP21-PMOS127-2D_pmos",
"SATOP31-PMOS132-2D_pmos": "SATOP31-PMOS132-2D_pmos",
"SINDI02-DSCR075_profiles": "SINDI02-DSCR075_profiles",
"SLAAR02-LPMO01-C321_proc": "SLAAR02-LPMO01-C321_proc",
@@ -87,5 +57,5 @@
"SLAAR21-LCAM-CS842_proc": "SLAAR21-LCAM-CS842_proc",
"SLAAR21-LCAM-CS843_proc": "SLAAR21-LCAM-CS843_proc",
"SLAAR21-LCAM-CS844_proc": "SLAAR21-LCAM-CS844_proc",
"test_str": "test_str"
"test_furka": "test_furka"
}
+4 -3
View File
@@ -44,6 +44,7 @@
"SAROP21-PBPS133_proc:9008",
"SARFE10-PPRM064_ib:9015",
"SATOP31-PMOS132-2D_sp",
"SATOP21-PMOS127-2D_pmos",
"SARFE10-PPRM064_sp",
"SARFE10-PPRM064_proc:9014",
"SATOP31-PMOS132-2D_pmos:9001",
@@ -217,7 +218,7 @@
"SARES20-PROF141-M1_proc:9016",
"SARES20-PROF141-M1_ib:9013",
"SARES20-PROF146-M1_sp",
"#SARES20-PROF146-M1_proc:9018",
"SARES20-PROF146-M1_proc:9018",
"SARES20-DSDPPRM_proc:9014",
"SARES20-DSDPPRM_ib:9020",
"SLAAR21-LCAM-CS841_proc:9021",
@@ -233,9 +234,9 @@
"http://sf-daqsync-15.psi.ch:8881": {
"cameras": [
"SATES31-CAMS187-RIXS1",
"SATES30-RIXS-CAM01",
"SATES30-CAMS182-GIGE1",
"SATES30-CAMS182-GIGE2"
"SATES30-CAMS182-GIGE2",
"SATES30-RIXS-CAM01"
],
"enabled": true,
"expanding": false,
@@ -8,7 +8,8 @@
"pipeline_type": "processing",
"camera_name": "simulation",
"name": "test_furka",
"function": "furka.py",
"_function": "furka.py",
"function": "single_photon.c",
"mode": "PUB",
"reload": true
}
+9 -2
View File
@@ -1,6 +1,6 @@
from collections import OrderedDict
from cam_server.pipeline.data_processing import functions, processor
import numpy as np
def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata):
r = processor.process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata)
@@ -8,5 +8,12 @@ def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata
channels = ["intensity","x_center_of_mass","x_fwhm","x_rms","x_fit_amplitude", "x_fit_mean","x_fit_offset","x_fit_standard_deviation","x_profile","y_center_of_mass","y_fwhm","y_rms","y_fit_amplitude", "y_fit_mean","y_fit_offset","y_fit_standard_deviation","y_profile"]
prefix = parameters["camera_name"]
for c in channels:
ret[prefix+":"+c] = r[c]
value = r[c]
if isinstance(value,np.floating):
value=float(value)
if isinstance(value,np.integer):
value=int(value)
if type(value) == list:
value = np.array(value)
ret[prefix+":"+c] = value
return ret
+157
View File
@@ -0,0 +1,157 @@
from logging import getLogger
from cam_server.pipeline.data_processing import functions
from cam_server.utils import create_thread_pvs, epics_lock
import json
import numpy
import scipy.signal
import scipy.optimize
import numba
numba.set_num_threads(4)
_logger = getLogger(__name__)
channel_names = None
output_pv, center_pv, fwhm_pv, ymin_pv, ymax_pv, axis_pv = None, None, None, None, None, None
roi = [0, 0]
initialized = False
sent_pid = -1
@numba.njit(parallel=True)
def get_spectrum(image, background):
y = image.shape[0]
x = image.shape[1]
profile = numpy.zeros(x, dtype=numpy.uint32)
for i in numba.prange(y):
for j in range(x):
v = image[i, j]
b = background[i, j]
if v > b:
v -= b
else:
v = 0
profile[j] += v
return profile
def initialize(parameters):
global ymin_pv, ymax_pv, axis_pv, output_pv, center_pv, fwhm_pv
global channel_names
epics_pv_name_prefix = parameters["camera_name"]
output_pv_name = epics_pv_name_prefix + ":SPECTRUM_Y"
center_pv_name = epics_pv_name_prefix + ":SPECTRUM_CENTER"
fwhm_pv_name = epics_pv_name_prefix + ":SPECTRUM_FWHM"
ymin_pv_name = epics_pv_name_prefix + ":SPC_ROI_YMIN"
ymax_pv_name = epics_pv_name_prefix + ":SPC_ROI_YMAX"
axis_pv_name = epics_pv_name_prefix + ":SPECTRUM_X"
channel_names = [output_pv_name, center_pv_name, fwhm_pv_name, ymin_pv_name, ymax_pv_name, axis_pv_name]
def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata=None, background=None):
global roi, initialized, sent_pid
global channel_names
if not initialized:
initialize(parameters)
initialized = True
[output_pv, center_pv, fwhm_pv, ymin_pv, ymax_pv, axis_pv] = create_thread_pvs(channel_names)
processed_data = dict()
epics_pv_name_prefix = parameters["camera_name"]
if ymin_pv and ymin_pv.connected:
roi[0] = ymin_pv.value
if ymax_pv and ymax_pv.connected:
roi[1] = ymax_pv.value
if axis_pv and axis_pv.connected:
axis = axis_pv.value
else:
axis = None
if axis is None:
_logger.warning("Energy axis not connected");
return None
if len(axis) < image.shape[1]:
_logger.warning("Energy axis length %d < image width %d", len(axis), image.shape[1])
return None
# match the energy axis to image width
axis = axis[:image.shape[1]]
processing_image = image
processing_image = image.astype(np.float32) - np.float32(parameters["pixel_bkg"])
nrows, ncols = processing_image.shape
# validate background data if passive mode (background subtraction handled here)
background_image = parameters.pop('background_data', None)
if isinstance(background_image, numpy.ndarray):
if background_image.shape != processing_image.shape:
_logger.info("Invalid background shape: %s instead of %s" % (
str(background_image.shape), str(processing_image.shape)))
background_image = None
else:
background_image = None
processed_data[epics_pv_name_prefix + ":processing_parameters"] = json.dumps(
{"roi": roi, "background": None if (background_image is None) else parameters.get('image_background')})
# crop the image in y direction
ymin, ymax = int(roi[0]), int(roi[1])
if nrows >= ymax > ymin >= 0:
if (nrows != ymax) or (ymin != 0):
processing_image = processing_image[ymin: ymax, :]
if background_image is not None:
background_image = background_image[ymin:ymax, :]
# remove the background and collapse in y direction to get the spectrum
if background_image is not None:
spectrum = get_spectrum(processing_image, background_image)
else:
spectrum = processing_image.sum(0, 'uint32')
# smooth the spectrum with savgol filter with 51 window size and 3rd order polynomial
smoothed_spectrum = scipy.signal.savgol_filter(spectrum, 51, 3)
# check wether spectrum has only noise. the average counts per pixel at the peak
# should be larger than 1.5 to be considered as having real signals.
minimum, maximum = smoothed_spectrum.min(), smoothed_spectrum.max()
amplitude = maximum - minimum
skip = True
if amplitude > nrows * 1.5:
skip = False
# gaussian fitting
offset, amplitude, center, sigma = functions.gauss_fit_psss(smoothed_spectrum[::2], axis[::2],
offset=minimum, amplitude=amplitude, skip=skip, maxfev=20)
# outputs
processed_data[epics_pv_name_prefix + ":SPECTRUM_Y"] = spectrum
processed_data[epics_pv_name_prefix + ":SPECTRUM_X"] = axis
processed_data[epics_pv_name_prefix + ":SPECTRUM_CENTER"] = numpy.float64(center)
processed_data[epics_pv_name_prefix + ":SPECTRUM_FWHM"] = numpy.float64(2.355 * sigma)
if epics_lock.acquire(False):
try:
if pulse_id > sent_pid:
sent_pid = pulse_id
if output_pv and output_pv.connected:
output_pv.put(processed_data[epics_pv_name_prefix + ":SPECTRUM_Y"])
#_logger.debug("caput on %s for pulse_id %s", output_pv, pulse_id)
if center_pv and center_pv.connected:
center_pv.put(processed_data[epics_pv_name_prefix + ":SPECTRUM_CENTER"])
if fwhm_pv and fwhm_pv.connected:
fwhm_pv.put(processed_data[epics_pv_name_prefix + ":SPECTRUM_FWHM"])
finally:
epics_lock.release()
return processed_data
+17 -2
View File
@@ -1,11 +1,26 @@
from collections import OrderedDict
from cam_server.pipeline.data_processing import functions, processor
from logging import getLogger
import numpy as np
_logger = getLogger(__name__)
def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata):
r = processor.process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata)
ret = OrderedDict()
channels = ["x_center_of_mass","y_center_of_mass"]
channels = ["intensity","x_fit_mean","y_fit_mean"]
prefix = parameters["camera_name"]
for c in channels:
ret[prefix+":"+c] = r[c]
value = r[c]
if value is None:
_logger.warning("None:" + str(c))
return None
if value == float('nan'):
_logger.warning("NAN:" + str(c))
return None
if isinstance(value,np.floating):
value=float(value)
if isinstance(value,np.integer):
value=int(value)
ret[prefix+":"+c] = value
return ret
+214
View File
@@ -0,0 +1,214 @@
#include "module.c"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
const char *CHANNEL_NAMES[] = {"EVENT_NUM", "EVENT_I", "EVENT_J", "EVENT_CHARGE", "EVENT_ETA_X", "EVENT_ETA_Y", "EVENT_I_INTERP", "EVENT_J_INTERP"};
const int MAX_NUM_EVENTS= 1000; // max number of events per frame
const int EVENT_CHANNELS = 7;
struct events_double func_ph_1d_double( double *frame, int i_dim, int j_dim, double *th_m);
//struct decl.
struct events_double {
double **evnt_ijc;
int evnt_num;
};
//def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata=None):
PyObject *process(PyObject *self, PyObject *args)
{
PyArrayObject *image;
long pulse_id;
PyObject /*double*/ *timestamp;
long seconds, nanos;
PyArrayObject *x_axis;
PyArrayObject *y_axis;
PyObject *pars;
PyObject *bsdata;
//if (!PyArg_ParseTuple(args, "OldOOO|O", &image, &pulse_id, &timestamp, &x_axis, &y_axis, &pars, &bsdata))
if ( !PyArg_ParseTuple(args, "OlOOOO|O", &image, &pulse_id, &timestamp, &x_axis, &y_axis, &pars, &bsdata) ||
!PyArg_ParseTuple(timestamp, "ll", &seconds, &nanos) )
return NULL;
if (pulse_id < 0) {
PyErr_SetString(moduleErr, "Invalid Pulse ID");
return NULL;
}
//Acessing image
int element_size = image->descr->elsize;
int dims = image->nd;
int size_x = image->dimensions[1];
int size_y = image->dimensions[0];
unsigned short* img_data = (unsigned short*)image->data;
int i,j,l;
int i_dim=size_y;
int j_dim=size_x;
double *threshold = malloc(i_dim*j_dim*sizeof(double));
for(i=0; i<i_dim;i++) {
for(j=0;j<j_dim;j++) {
threshold[i*j_dim+j]=90.0;
}
}
//background (all matrices are indexed in 1d)
double *background = malloc(i_dim*j_dim*sizeof(double));
for(i=0; i<i_dim;i++) {
for(j=0;j<j_dim;j++) {
background[i*j_dim+j]=10.0;
}
}
double *frameBKsub = malloc(i_dim*j_dim*sizeof(double));
for(i=0; i<i_dim;i++) {
for(j=0;j<j_dim;j++) {
frameBKsub[i*j_dim+j]=(double)img_data[i*j_dim+j] - background[i*j_dim+j];
}
}
struct events_double evns1d = func_ph_1d_double( frameBKsub, i_dim, j_dim, threshold);
//Create return dictionary
PyObject *ret = PyDict_New();
PyObject* camera_name = PyDict_GetItemString(pars, "camera_name");
const char * camera_name_str = PyUnicode_AsUTF8(camera_name);
char channel_name[200];
//PyDict_SetItemString(ret, "camera_name", camera_name);
sprintf(channel_name, "%s:%s",camera_name_str, CHANNEL_NAMES[0]);
PyDict_SetItemString(ret, channel_name, PyLong_FromLong(evns1d.evnt_num));
for (int i=0; i<EVENT_CHANNELS; i++){
sprintf(channel_name, "%s:%s",camera_name_str, CHANNEL_NAMES[i+1]);
npy_intp arr_dims[1] = {MAX_NUM_EVENTS};
PyObject *parr =PyArray_SimpleNewFromData(1, arr_dims, NPY_FLOAT64, evns1d.evnt_ijc);
PyDict_SetItemString(ret, channel_name, parr);
}
for (l = 0; l < EVENT_CHANNELS; l++) {
free(evns1d.evnt_ijc[l]);
}
free(evns1d.evnt_ijc);
free(frameBKsub);
free(background);
free(threshold);
return ret;
}
struct events_double func_ph_1d_double( double *frame, int i_dim, int j_dim, double *th_m)
{
//int th= 50;
int i, j, l=0, m=0, n=0, evt_m_i=0, evt_i=0 ;
int dist_i, dist_j;
double charge_evt;
int th;
double **evt_p= (double**)malloc(EVENT_CHANNELS * sizeof(double*));
for (l = 0; l < EVENT_CHANNELS; l++) {
evt_p[l] = (double*)malloc(MAX_NUM_EVENTS * sizeof(double));}
/*Counter variables for the loop*/
double charge = 0;
double eta_x = 0;
double eta_y = 0;
double i_interp = 0;
double j_interp = 0;
double C[]= { 4.37805097e-03, 2.43266401e-01, -7.81479328e+00, 7.70533057e+01, -2.37906124e+02, 3.42988113e+02, -2.35979731e+02, 6.24074562e+01};
double D[]= {-2.05180773e-04, 4.35314696e-01, -1.32557223e+01, 1.19990373e+02, -3.80696758e+02, 5.81427096e+02, -4.30789104e+02, 1.23894761e+02};
for(i=0; i<i_dim-1; i++) {
if (evt_i>=MAX_NUM_EVENTS){
break;
}
for(j=0;j<j_dim-1;j++) {
if (evt_i>=MAX_NUM_EVENTS){
break;
}
// 2x2 version
charge = frame[i*j_dim+j]+frame[(i+1)*j_dim+j] + frame[i*j_dim+(j+1)]+frame[(i+1)*j_dim+j+1];
//pixel by pixel threshold
th = th_m[i*j_dim +j];
//check if charge above threshold
if(charge>th) {
eta_x = (frame[(i+1)*j_dim + j ]+frame[(i+1)*j_dim + (j+1)])/charge;
eta_y = (frame[ i*j_dim + (j+1)]+frame[(i+1)*j_dim + (j+1)])/charge;
i_interp = i + (C[0] + C[1]*eta_x+ C[2]*pow(eta_x,2) + C[3]*pow(eta_x,3) + C[4]*pow(eta_x,4)+ C[5]*pow(eta_x,5) + C[6]*pow(eta_x,6) + C[7]*pow(eta_x,7));
j_interp = j + (D[0] + D[1]*eta_y+ D[2]*pow(eta_y,2) + D[3]*pow(eta_y,3) + D[4]*pow(eta_y,4)+ D[5]*pow(eta_y,5) + D[6]*pow(eta_y,6) + D[7]*pow(eta_y,7));
// 1st case: first event
if(evt_i==0){
evt_p[0][evt_i] = i;
evt_p[1][evt_i] = j;
evt_p[2][evt_i] = charge;
evt_p[3][evt_i] = eta_x;
evt_p[4][evt_i] = eta_y;
evt_p[5][evt_i] = i_interp; //
evt_p[6][evt_i] = j_interp; //
evt_i++;
} else {
// 2nd case: not 1st event. we check if it is a neighbourg of the previos events and if charge is larger
n=0;
evt_m_i = evt_i;
for(m=0; m<evt_m_i; m++) {
dist_i = abs(evt_p[0][evt_i-1-m] - i); //fix here
dist_j = abs(evt_p[1][evt_i-1-m] - j);
charge_evt = evt_p[2][evt_i-1-m];
if( dist_i< 2 && dist_j<2) {
if(charge_evt < charge) {
//2nd case: not 1st event, but neigboor of previos event, this event has more charge
evt_p[0][evt_i-1-m] = i;
evt_p[1][evt_i-1-m] = j;
evt_p[2][evt_i-1-m] = charge;
evt_p[3][evt_i-1-m] = eta_x;
evt_p[4][evt_i-1-m] = eta_y;
evt_p[5][evt_i-1-m] = i_interp;
evt_p[6][evt_i-1-m] = j_interp;
} else {
//3d case not 1st event, but neigboor of previos event, this event has less charge
}
} else {
// not a neighbor of the m event
n++;
//now we check if it is not a neighborg of any previous event
if((n)==evt_i) {
evt_p[0][evt_i] = i;
evt_p[1][evt_i] = j;
evt_p[2][evt_i] = charge;
evt_p[3][evt_i] = eta_x;
evt_p[4][evt_i] = eta_y;
evt_p[5][evt_i] = i_interp; //
evt_p[6][evt_i] = j_interp; //
evt_i++;
}
}
}
}
}
}
}
struct events_double events_i_d;
events_i_d.evnt_ijc = evt_p;
events_i_d.evnt_num = evt_i;
return events_i_d;
}
+18
View File
@@ -0,0 +1,18 @@
from collections import OrderedDict
from cam_server.pipeline.data_processing import functions, processor
def process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata):
ret = OrderedDict()
r = processor.process_image(image, pulse_id, timestamp, x_axis, y_axis, parameters, bsdata)
channels = ["intensity","x_fit_mean","y_fit_mean"]
prefix = parameters["camera_name"]
#for c in channels:
# ret[prefix+":"+c] = r[c]
ret[prefix+":intensity"] = r["intensity"]
ret[prefix+":x_fit_mean_v2"] = r["x_fit_mean"]
ret[prefix+":y_fit_mean"] = r["y_fit_mean"]
#ret["SARES20-PROF141-M1:intensity"] = 1281954
#ret["SARES20-PROF141-M1:x_fit_mean"] = 708.7
#ret["SARES20-PROF141-M1:y_fit_mean"] = 539.3
return ret