rcdb 0.9.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rcdb/__init__.py ADDED
@@ -0,0 +1,128 @@
1
+ from .model import ConditionType
2
+ from .provider import RCDBProvider
3
+ from .provider import ConfigurationProvider
4
+ from .rcdb_cli.app import rcdb_cli as run_rcdb_cli
5
+
6
+
7
+ # This thing separates cells in data blob
8
+ blob_delimiter = "|"
9
+
10
+ # if cell of data table is a string and the string already contains blob_delimiter
11
+ # we have to encode blob_delimiter to blob_delimiter_replace on data write and decode it bach on data read
12
+ blob_delimiter_replacement = "&delimiter;"
13
+
14
+ SQL_SCHEMA_VERSION = 2
15
+
16
+
17
+ class UpdateReasons(object):
18
+ """Class holds a default values of UpdateContext.reason field
19
+ Attributes:
20
+ START - means update goes after 'GO', beginning of the data taking
21
+ UPDATE - after run in started, RCDB is being update each minute. That is how it is done
22
+ END - after run is ended
23
+ """
24
+ START = 'start'
25
+ UPDATE = 'update'
26
+ END = 'end'
27
+ UNKNOWN = ''
28
+
29
+
30
+ # -------------------------------------------------
31
+ # class holding a context of the update operations
32
+ # -------------------------------------------------
33
+ class UpdateContext(object):
34
+ """Updates context
35
+
36
+ Attributes:
37
+ self.db - RCDBProvider with connection
38
+ self.reason - one of UpdateReasons or empty string
39
+ self.run - Run object
40
+ """
41
+
42
+ def __init__(self, db, reason):
43
+ self.db = db
44
+ self.reason = reason # Context in which daq is called '', 'start', 'update', 'end'
45
+ self.run = None # Run object
46
+
47
+
48
+ # -------------------------------------------------
49
+ # function Convert list to DB text representation
50
+ # -------------------------------------------------
51
+ def list_to_db_text(values):
52
+ """
53
+ Converts list of values like pedestal,threshold,baseline_preset values
54
+ to a space separated string - that is how the values are stored in the DB
55
+
56
+ :param values: list of values
57
+ :type values: []
58
+
59
+ :return: string with values as it is stored in DB
60
+ :rtype: basestring
61
+ """
62
+ return " ".join([str(value) for value in values])
63
+
64
+
65
+ def make_threshold_preset(db, board, values):
66
+ """
67
+ checks if values
68
+ :param values:
69
+ :return:
70
+ """
71
+
72
+ if isinstance(values, list):
73
+ text_values = list_to_db_text(values)
74
+
75
+
76
+ class DefaultConditions(object):
77
+ """
78
+ Holds common names for conditions and can ensure database have them
79
+ """
80
+
81
+ EVENT_RATE = 'event_rate'
82
+ EVENT_COUNT = 'event_count'
83
+ RUN_TYPE = 'run_type'
84
+ RUN_CONFIG = 'run_config'
85
+ RUN_LENGTH = 'run_length'
86
+ RUN_START_TIME = 'run_start_time'
87
+ RUN_END_TIME = 'run_end_time'
88
+ DAQ_SETUP = 'daq_setup'
89
+ SESSION = 'session'
90
+ USER_COMMENT = 'user_comment'
91
+ COMPONENTS = 'components'
92
+ COMPONENT_STATS = 'component_stats'
93
+ RTVS = 'rtvs'
94
+ IS_VALID_RUN_END = 'is_valid_run_end'
95
+
96
+
97
+ def create_default_condition_types(db):
98
+ """
99
+ Checks if condition types listed in class exist in the database and create them if not
100
+ :param db: RCDBProvider connected to database
101
+ :type db: RCDBProvider
102
+
103
+ :return: None
104
+ """
105
+ all_types_dict = {t.name: t for t in db.get_condition_types()}
106
+
107
+ def create_condition_type(name, value_type, description=""):
108
+ all_types_dict[name] if name in all_types_dict.keys() \
109
+ else db.create_condition_type(name, value_type, description)
110
+
111
+ # get or create condition type
112
+ create_condition_type(DefaultConditions.EVENT_RATE, ConditionType.FLOAT_FIELD, "Average event rate")
113
+ create_condition_type(DefaultConditions.EVENT_COUNT, ConditionType.INT_FIELD, "Number of events")
114
+ create_condition_type(DefaultConditions.RUN_TYPE, ConditionType.STRING_FIELD, "DAQ Run type")
115
+ create_condition_type(DefaultConditions.RUN_CONFIG, ConditionType.STRING_FIELD, "DAQ Run configuration")
116
+ create_condition_type(DefaultConditions.SESSION, ConditionType.STRING_FIELD)
117
+ create_condition_type(DefaultConditions.USER_COMMENT, ConditionType.STRING_FIELD)
118
+ create_condition_type(DefaultConditions.COMPONENTS, ConditionType.JSON_FIELD)
119
+ create_condition_type(DefaultConditions.RTVS, ConditionType.JSON_FIELD)
120
+ create_condition_type(DefaultConditions.COMPONENT_STATS, ConditionType.JSON_FIELD)
121
+ create_condition_type(DefaultConditions.IS_VALID_RUN_END, ConditionType.BOOL_FIELD,
122
+ "True if a run has valid run-end record. "
123
+ "False means the run was aborted/crashed at some point")
124
+ create_condition_type(DefaultConditions.RUN_LENGTH, ConditionType.INT_FIELD, "Length of the run ")
125
+ create_condition_type(DefaultConditions.RUN_START_TIME, ConditionType.TIME_FIELD, "Run start time ")
126
+ create_condition_type(DefaultConditions.RUN_END_TIME, ConditionType.TIME_FIELD, "Run end time (last CODA update)")
127
+
128
+
rcdb/__main__.py ADDED
@@ -0,0 +1,3 @@
1
+ from rcdb.rcdb_cli.app import rcdb_cli
2
+
3
+ rcdb_cli()
rcdb/admin_cmd.py ADDED
@@ -0,0 +1,88 @@
1
+ import os
2
+ import sys
3
+ import posixpath
4
+
5
+ import click
6
+
7
+ from rcdb.app_context import RcdbApplicationContext, parse_run_range
8
+ from rcdb import RCDBProvider
9
+
10
+ pass_rcdb_context = click.make_pass_decorator(RcdbApplicationContext)
11
+
12
+
13
+ def get_default_config_path():
14
+ return os.path.join(os.path.expanduser('~'), '.rcdb_user')
15
+
16
+
17
+ @click.group()
18
+ @click.option('--user-config', envvar='RCDB_USER_CONFIG', default=get_default_config_path, metavar='PATH', help='Changes the user config location.')
19
+ @click.option('--connection', '-c', envvar='RCDB_CONNECTION', help='Database connection string', default=None, required=True)
20
+ @click.option('--config', nargs=2, multiple=True, metavar='KEY VALUE', help='Overrides a config key/value pair.')
21
+ @click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.')
22
+ @click.version_option('1.0')
23
+ @click.pass_context
24
+ def cli(ctx, user_config, connection, config, verbose):
25
+ """'rcdb' is a RCDB (run conditions database) command line tool
26
+
27
+ This tool allows to select runs and get values as well as manage RCDB values
28
+ """
29
+
30
+ # Create a rcdb_app_context object and remember it as as the context object. From
31
+ # this point onwards other commands can refer to it by using the
32
+ # @pass_rcdb_context decorator.
33
+ ctx.obj = RcdbApplicationContext(os.path.abspath(user_config), connection)
34
+ ctx.obj.verbose = verbose
35
+ for key, value in config:
36
+ ctx.obj.set_config(key, value)
37
+
38
+
39
+ @cli.command(help="")
40
+ @click.argument('search', required=False)
41
+ @click.option('--long', '-l', 'is_long', is_flag=True, help='Prints condition full information')
42
+ @pass_rcdb_context
43
+ def walk(context, search, is_long):
44
+ """Lists condition
45
+
46
+
47
+ """
48
+ db = context.db
49
+ assert isinstance(db, RCDBProvider)
50
+ cnd_types = db.get_condition_types_by_name()
51
+ names = sorted(cnd_types.keys())
52
+ if search:
53
+ names = [n for n in names if search in n]
54
+
55
+ longest_len = len(max(names, key=len))
56
+ for name in names:
57
+ cnd_type = cnd_types[name]
58
+ click.echo("{0:<{1}} {2}".format(name, longest_len, cnd_type.description))
59
+
60
+ @cli.command()
61
+ @click.argument('search', required=False)
62
+ @click.option('--long', '-l', 'is_long', is_flag=True, help='Prints condition full information')
63
+ @pass_rcdb_context
64
+ def ls(context, search, is_long):
65
+ """Lists condition
66
+
67
+
68
+ """
69
+ db = context.db
70
+ assert isinstance(db, RCDBProvider)
71
+ cnd_types = db.get_condition_types_by_name()
72
+ names = sorted(cnd_types.keys())
73
+ if search:
74
+ names = [n for n in names if search in n]
75
+
76
+ longest_len = len(max(names, key=len))
77
+ for name in names:
78
+ cnd_type = cnd_types[name]
79
+ click.echo("{0:<{1}} {2}".format(name, longest_len, cnd_type.description))
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+ if __name__ == '__main__':
88
+ cli(prog_name="rcdb")
rcdb/alias.py ADDED
@@ -0,0 +1,90 @@
1
+ class ConditionSearchAlias(object):
2
+ def __init__(self, name, expression, comment):
3
+ self.name = name
4
+ self.expression = expression
5
+ self.comment = comment
6
+
7
+
8
+ default_aliases = [
9
+ ConditionSearchAlias('is_production', """run_type in ['hd_all.tsg', 'hd_all.tsg_ps', 'hd_all.bcal_fcal_st.tsg'] and
10
+ beam_current and beam_current > 2 and
11
+ event_count > 500000 and
12
+ solenoid_current and solenoid_current > 100 and
13
+ collimator_diameter != 'Blocking'""",
14
+ "Is production run"),
15
+
16
+ ConditionSearchAlias('is_2018production', """daq_run == 'PHYSICS' and
17
+ beam_current > 2 and
18
+ event_count > 10000000 and
19
+ solenoid_current > 100 and
20
+ collimator_diameter != 'Blocking'""",
21
+ "Is production run"),
22
+
23
+ ConditionSearchAlias('is_primex_production', """daq_run == 'PHYSICS_PRIMEX' and
24
+ event_count > 1000000 and
25
+ collimator_diameter != 'Blocking'""",
26
+ "Is PrimEx production run"),
27
+
28
+ ConditionSearchAlias('is_dirc_production', """daq_run == 'PHYSICS_DIRC' and
29
+ beam_current > 2 and
30
+ event_count > 5000000 and
31
+ solenoid_current > 100 and
32
+ collimator_diameter != 'Blocking'""",
33
+ "Is DIRC production run"),
34
+
35
+ ConditionSearchAlias('is_src_production', """daq_run == 'PHYSICS_SRC' and
36
+ beam_current > 2 and
37
+ event_count > 5000000 and
38
+ solenoid_current > 100 and
39
+ collimator_diameter != 'Blocking'""",
40
+ "Is SRC production run"),
41
+
42
+ ConditionSearchAlias('is_cpp_production', """daq_run == 'PHYSICS_CPP' and
43
+ beam_current > 2 and
44
+ event_count > 5000000 and
45
+ solenoid_current > 100 and
46
+ collimator_diameter != 'Blocking'""",
47
+ "Is CPP production run"),
48
+
49
+ ConditionSearchAlias('is_production_long', """daq_run == 'PHYSICS_raw'
50
+ beam_current > 2 and
51
+ event_count > 5000000 and
52
+ solenoid_current > 100 and
53
+ collimator_diameter != 'Blocking'""",
54
+ "Is production run with long mode data"),
55
+
56
+ ConditionSearchAlias('is_cosmic', '"cosmic" in run_config and beam_current < 1 and event_count > 5000',
57
+ "Is cosmic run"),
58
+
59
+ ConditionSearchAlias('is_empty_target', "target_type == 'EMPTY & Ready'", "Target is empty"),
60
+
61
+ # These should be true starting in 2017. Need to check to make sure that 2016 data is accurate...
62
+ ConditionSearchAlias('is_amorph_radiator', "polarization_angle < 0.", "Amorphous Radiator"),
63
+ ConditionSearchAlias('is_coherent_beam', "polarization_angle >= 0.", "Coherent Beam"),
64
+ #ConditionSearchAlias('is_amorph_radiator', "radiator_index == -1 and radiator_type != 'None' and target_type == 'FULL & Ready'",
65
+ # "Amorphous Radiator"),
66
+ #ConditionSearchAlias('is_coherent_beam', "(radiator_id != 5 and radiator_id > 0) and target_type == 'FULL & Ready'", "Coherent Beam"),
67
+
68
+ ConditionSearchAlias('is_field_off', "solenoid_current < 100", " Field Off"),
69
+
70
+ ConditionSearchAlias('is_field_on', "solenoid_current >= 100", " Field On"),
71
+
72
+ ConditionSearchAlias('status_calibration', "status == 3", "Run status = calibration"),
73
+
74
+ ConditionSearchAlias('status_approved_long', "status == 2", "Run status = approved (long)"),
75
+
76
+ ConditionSearchAlias('status_approved', "status == 1", "Run status = approved"),
77
+
78
+ ConditionSearchAlias('status_unchecked', "status == -1", "Run status = unchecked"),
79
+
80
+ ConditionSearchAlias('status_reject', " status == 0", "Run status = reject"),
81
+ ]
82
+
83
+ _def_al_by_name = None
84
+
85
+
86
+ def get_default_aliases_by_name():
87
+ global _def_al_by_name
88
+ if _def_al_by_name is None:
89
+ _def_al_by_name = {al.name:al for al in default_aliases }
90
+ return _def_al_by_name
rcdb/app_context.py ADDED
@@ -0,0 +1,100 @@
1
+ import click
2
+ from rcdb import RCDBProvider
3
+ import sys
4
+
5
+
6
+ class RcdbApplicationContext(object):
7
+
8
+ def __init__(self, home, connection_str):
9
+ self.home = home
10
+ self._db_instance = None
11
+
12
+ self.config = {}
13
+ self.verbose = False
14
+ self.connection_str = connection_str
15
+
16
+ @property
17
+ def db(self):
18
+ if not self._db_instance:
19
+ self._db_instance = RCDBProvider(self.connection_str)
20
+ return self._db_instance
21
+
22
+ def set_config(self, key, value):
23
+ self.config[key] = value
24
+ if self.verbose:
25
+ click.echo(' config[%s] = %s' % (key, value), file=sys.stderr)
26
+
27
+ def __repr__(self):
28
+ return '<Repo %r>' % self.home
29
+
30
+
31
+ class RcdbAdminApplicationContext(RcdbApplicationContext):
32
+
33
+ def __init__(self, home, connection_str):
34
+ super(RcdbAdminApplicationContext).__init__(home, connection_str)
35
+
36
+
37
+ def parse_run_range(run_range_str, run_periods=None):
38
+ """ Parses run range, returning a pair (run_from, run_to) or (run_from, None) or (None, None)
39
+
40
+ Function doesn't raise FormatError
41
+ :exception ValueError: if run_range_str is not str
42
+
43
+ :param run_range_str: string to parse
44
+ :return: (run_from, run_to). Function always return lower run number as run_from
45
+ """
46
+
47
+ if run_range_str is None:
48
+ return None, None
49
+
50
+ run_range_str = str(run_range_str).strip()
51
+ if not run_range_str:
52
+ return None, None
53
+
54
+ assert isinstance(run_range_str, str)
55
+
56
+ # Is it run period?
57
+ if run_periods:
58
+ if run_range_str in run_periods:
59
+ run_min, run_max, descr = run_periods[run_range_str]
60
+ return run_min, run_max
61
+
62
+ # Have run-range?
63
+ if '-' in run_range_str:
64
+ tokens = [t.strip() for t in run_range_str.split("-")]
65
+ try:
66
+ run_from = int(tokens[0])
67
+ except (ValueError, KeyError):
68
+ return None, None
69
+
70
+ try:
71
+ run_to = int(tokens[1])
72
+ except (ValueError, KeyError):
73
+ return run_from, None
74
+
75
+ return (run_from, run_to) if run_from <= run_to else (run_to, run_from)
76
+
77
+ # Have run number?
78
+ if run_range_str.isdigit():
79
+ return int(run_range_str), None
80
+
81
+ # Default return is index
82
+ return None, None
83
+
84
+
85
+ def minmax_run_range(run_range: tuple):
86
+ """If one or both values of run_range tuple is None, replaces it to 0 or sys.maxsize
87
+
88
+ > minmax_run_range((None, None))
89
+ (0, sys.maxsize)
90
+ > minmax_run_range((None, value2))
91
+ (0, value2)
92
+ > minmax_run_range((value1, None))
93
+ (value1, sys.maxsize)
94
+ > minmax_run_range((value1, value2))
95
+ (value1, value2)
96
+ """
97
+
98
+ min_run = 0 if run_range[0] is None else run_range[0]
99
+ max_run = sys.maxsize if run_range[1] is None else run_range[1]
100
+ return min_run, max_run