sardana-nxsrecorder 3.13.2__py3-none-any.whl → 3.30.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.
@@ -1,19 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sardana-nxsrecorder
3
- Version: 3.13.2
3
+ Version: 3.30.1
4
4
  Summary: NeXus Sardana Scan Recorder
5
5
  Home-page: https://github.com/nexdatas/sardana-nxs-filerecorder/
6
6
  Author: Jan Kotanski
7
7
  Author-email: jankotan@gmail.com
8
8
  License: GNU GENERAL PUBLIC LICENSE v3
9
9
  Keywords: NeXus sardana scan recorder data
10
- Platform: UNKNOWN
11
10
  Classifier: Development Status :: 5 - Production/Stable
12
11
  Classifier: Intended Audience :: Science/Research
13
12
  Classifier: Topic :: Scientific/Engineering :: Physics
14
13
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
14
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
16
- Classifier: Programming Language :: Python :: 2.7
17
15
  Classifier: Programming Language :: Python :: 3
18
16
  Classifier: Programming Language :: Python :: 3.4
19
17
  Classifier: Programming Language :: Python :: 3.5
@@ -23,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.8
23
21
  Classifier: Programming Language :: Python :: 3.9
24
22
  Classifier: Programming Language :: Python :: 3.10
25
23
  Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
26
25
  Requires-Dist: lxml
27
26
  Requires-Dist: numpy (>1.6.0)
28
27
 
@@ -77,7 +76,7 @@ Extract sources and run
77
76
 
78
77
  .. code-block:: console
79
78
 
80
- $ python setup.py install
79
+ $ python3 setup.py install
81
80
 
82
81
  and add an *RecorderPath* property of *MacroServer* with its value
83
82
  defining the package location, e.g.
@@ -88,21 +87,22 @@ defining the package location, e.g.
88
87
  Debian packages
89
88
  """""""""""""""
90
89
 
91
- Debian Bookworm, Bullseye, Buster and Ubuntu Lunar, Jammy and Focal packages can be found in the HDRI repository.
90
+ Debian Trixie, Bookworm, Bullseye and Ubuntu Questing, Noble Jammy packages can be found in the HDRI repository.
92
91
 
93
92
  To install the debian packages, add the PGP repository key
94
93
 
95
94
  .. code-block:: console
96
95
 
97
96
  $ sudo su
98
- $ wget -q -O - http://repos.pni-hdri.de/debian_repo.pub.gpg | apt-key add -
97
+ $ curl -s http://repos.pni-hdri.de/debian_repo.pub.gpg | gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/debian-hdri-repo.gpg --import
98
+ $ chmod 644 /etc/apt/trusted.gpg.d/debian-hdri-repo.gpg
99
99
 
100
100
  and then download the corresponding source list
101
101
 
102
102
  .. code-block:: console
103
103
 
104
104
  $ cd /etc/apt/sources.list.d
105
- $ wget http://repos.pni-hdri.de/bookworm-pni-hdri.list
105
+ $ wget http://repos.pni-hdri.de/trixie-pni-hdri.sources
106
106
 
107
107
 
108
108
  Finally, for python2.7
@@ -110,7 +110,7 @@ Finally, for python2.7
110
110
  .. code-block:: console
111
111
 
112
112
  $ apt-get update
113
- $ apt-get install python-sardana-nxsrecorder
113
+ $ apt-get install python3-sardana-nxsrecorder
114
114
 
115
115
  and set the RecoderPath property of MacroServer with
116
116
 
@@ -118,34 +118,15 @@ and set the RecoderPath property of MacroServer with
118
118
 
119
119
  $ apt-get install sardana-nxsrecorder
120
120
 
121
- For python3
122
-
123
- .. code-block:: console
124
-
125
- $ apt-get update
126
- $ apt-get install python3-sardana-nxsrecorder
127
- $ apt-get install sardana-nxsrecorder3
128
121
 
129
122
  To instal other NexDaTaS packages
130
123
 
131
- .. code-block:: console
132
-
133
- $ apt-get install python-nxswriter nxsconfigserver-db python-nxsconfigserver nxsconfigtool python-nxstools nxswriter nxsconfigserver nxsrecselector
134
-
135
- or for python 3
136
-
137
124
  .. code-block:: console
138
125
 
139
126
  $ apt-get install python3-nxswriter nxsconfigserver-db python3-nxsconfigserver nxsconfigtool3 python3-nxstools nxswriter3 nxsconfigserver3
140
127
 
141
128
  and
142
129
 
143
- .. code-block:: console
144
-
145
- $ apt-get install python-nxsrecselector nxsrecselector nxselector
146
-
147
- or for python3
148
-
149
130
  .. code-block:: console
150
131
 
151
132
  $ apt-get install python3-nxsrecselector nxsrecselector3 nxselector3
@@ -237,6 +218,8 @@ The NeXus file recorder uses the following sardana environment variables
237
218
 
238
219
  * **ActiveMntGrp** *(str)* - active measurement group
239
220
  * **ScanID** *(int)* - the last scan identifier number, default: ``-1``
221
+ * **ScanDir** *(str)* - the scan directory
222
+ * **ScanFile** *(list)* - a list of scan files
240
223
  * **NeXusSelectorDevice** *(str)* - NXSRecSelector tango device if more installed, otherwise first one found
241
224
 
242
225
  * **NXSAppendSciCatDataset** *(bool)* - append scan name to scicat dataset list file, default: ``False``
@@ -246,5 +229,21 @@ The NeXus file recorder uses the following sardana environment variables
246
229
  * **SciCatDatasetListFilePrefix** *(str)* - scicat dataset list file prefix, default: ``"scicat-datasets-"``
247
230
  * **SciCatDatasetListFileExt** *(str)* - scicat dataset list file extension, default: ``".lst"``
248
231
  * **SciCatDatasetListFileLocal** *(bool)* - add the hostname to the scicat dataset list file extension, default: ``False``
232
+ * **SciCatAutoGrouping** *(bool)* - group all scans with the measurement name set to the base scan filename, default: ``False``
233
+ * **MetadataScript** *(str)* - a python module file name containing ``main()`` which provides a dictionary with user metadata stored in the INIT mode, default: ``""``
234
+ * **ScicatMeasurements** *(dict)* - a dictionary of measurement names indexed by ``ScanDir`` and used by ``scingestor``, default: ``{}``
235
+ * **CreateMeasurementFile** *(bool)* - create a measurement file with its filename releated to ``ScicatMeasurements`` or ``ScanFile``, default: ``False``
236
+ * **NeXusWriterProperties** *(dict)* - a dictionary of TangoDataWriter (NXSDataWriter) properties (starting with a small letter)
237
+ * **NeXusMeshScanID** *(int)* - ScanID used for composed scans e.g. mesh scan combined from many linear scans
238
+ * **NeXusWriterModes** *(list)* - a list of strategy modes e.g. ``NOINIT``, ``NOSTEP``, ``NOFINAL``, ``MESH``, ``VDS`` separated by commas
239
+ * **ScanNames** *(bool)* - special mode of using ScanName directories i.e.
240
+
241
+ * ``True``: the master file in the ScanName directory,
242
+
243
+ * ``False``: the master file in the grouping ScanName directory (e.g. without ScanID),
249
244
 
245
+ * ``None`` (or undefined): standard mode where the master files are outside the ScanName directory
250
246
 
247
+ * **ScanNamesNoGrouping** *(bool)* - do not perform grouping when ``ScanNames`` is ``False``
248
+ * **ScanNamesNoMetadata** *(bool)* - do not perform master file metadata ingestion when ``ScanNames`` is ``False``
249
+
@@ -0,0 +1,6 @@
1
+ sardananxsrecorder/__init__.py,sha256=E5trFSG5M-GbgxeR_3kAvsnEtOAN4aKJbIHF0jDu95k,896
2
+ sardananxsrecorder/nxsrecorder.py,sha256=YVH1Y92qGEviUno_j1TsGAGvEKgF2sRYOho72WMkuq4,67052
3
+ sardana_nxsrecorder-3.30.1.dist-info/METADATA,sha256=ZVF0ds6Y9meFfEziBW8Th1lue3OeTOLZy5QxaLybsME,8256
4
+ sardana_nxsrecorder-3.30.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
5
+ sardana_nxsrecorder-3.30.1.dist-info/top_level.txt,sha256=YdD3m417i-jlYyQWgiizgZ8lQQcOjM8y-bmUHrGkfY4,19
6
+ sardana_nxsrecorder-3.30.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: bdist_wheel (0.38.4)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -20,4 +20,4 @@
20
20
  """ Sardana Scan Recorders """
21
21
 
22
22
  #: package version
23
- __version__ = "3.13.2"
23
+ __version__ = "3.30.1"
@@ -22,10 +22,10 @@
22
22
 
23
23
  import os
24
24
  import re
25
+ import sys
25
26
 
26
27
  import numpy
27
28
  import json
28
- import pytz
29
29
  import time
30
30
  import weakref
31
31
  import socket
@@ -35,6 +35,15 @@ try:
35
35
  except Exception:
36
36
  import PyTango as tango
37
37
 
38
+ try:
39
+ NXSWRITER = True
40
+ try:
41
+ from nxstools import h5cppwriter as h5writer
42
+ except Exception:
43
+ from nxstools import h5pywriter as h5writer
44
+ except Exception:
45
+ NXSWRITER = False
46
+
38
47
 
39
48
  from sardana.macroserver.scan.recorder.storage import BaseFileRecorder
40
49
 
@@ -90,8 +99,11 @@ class NXS_FileRecorder(BaseFileRecorder):
90
99
  :type macro: :class:`sardana.macroserver.macro.Macro`
91
100
  """
92
101
  BaseFileRecorder.__init__(self)
102
+ self.debug('__init__: Init NXS_FileRecorder: %s' % str(filename))
93
103
  #: (:obj:`str`) base filename
94
104
  self.__base_filename = filename
105
+ #: (:obj:`str`) raw filename
106
+ self.__raw_filename = ""
95
107
  self.__macro = weakref.ref(macro) if macro else None
96
108
  #: (:class:`tango.Database`) tango database
97
109
  self.__db = tango.Database()
@@ -105,7 +117,8 @@ class NXS_FileRecorder(BaseFileRecorder):
105
117
  self.__nexussettings_device = None
106
118
 
107
119
  #: (:obj:`int`) device proxy timeout
108
- self.__timeout = 100000
120
+ # self.__timeout = 100000
121
+ self.__timeout = 10000000
109
122
  #: (:obj:`dict` <:obj:`str`, :obj:`list` <:obj:`str`>
110
123
  #: or :obj:`dict` <:obj:`str` , `any`> > ) Custom variables
111
124
  self.__vars = {"data": {},
@@ -140,19 +153,53 @@ class NXS_FileRecorder(BaseFileRecorder):
140
153
  #: (:obj:`str`) module lable
141
154
  self.__moduleLabel = 'module'
142
155
 
156
+ #: (:obj:`int`) serialno
157
+ self.__serial = 0
158
+
143
159
  #: (:obj:`dict` <:obj:`str` , :obj:`str`>) NeXus configuration
144
160
  self.__conf = {}
145
161
 
162
+ #: (:obj:`list` <:obj:`str`>) acquisition Modes
163
+ self.writerModes = self.__variableList(
164
+ "NeXusWriterModes")
165
+
166
+ #: (:obj:`dict` <:obj:`str` , `any`>) User data
167
+ self.__udata = None
168
+
146
169
  #: (:obj:`bool`) external measurement group
147
170
  self.__oddmntgrp = False
148
171
 
172
+ self.debug('__init__: Set NeXus: %s' % str(filename))
149
173
  self.__setNexusDevices(onlyconfig=True)
150
174
 
175
+ self.debug('__init__: Set Append Entry: %s' % str(filename))
151
176
  appendentry = self.__getConfVar("AppendEntry", True)
152
177
  scanID = self.__env["ScanID"] \
153
178
  if "ScanID" in self.__env.keys() else -1
154
- appendentry = not self.__setFileName(
179
+ self.debug('__init__: Set FileName: %s' % str(filename))
180
+ self.__setFileName(
155
181
  self.__base_filename, not appendentry, scanID)
182
+ self.debug('__init__: Done: %s' % str(filename))
183
+
184
+ def _serial(self, scanID):
185
+ serial = None
186
+ if "NOINIT" in self.writerModes and \
187
+ "MESH" in self.writerModes:
188
+ if self.__macro:
189
+ serial = self.__macro().getEnv('NeXusMeshScanID', None)
190
+ if serial is None:
191
+ if scanID is None:
192
+ serial = self.recordlist.getEnvironValue('serialno')
193
+ elif scanID >= 0:
194
+ if isarver >= 304 or isarver == 0:
195
+ serial = scanID
196
+ else:
197
+ serial = scanID + 1
198
+ if "MESH" in self.writerModes and \
199
+ "NOINIT" not in self.writerModes:
200
+ if self.__macro:
201
+ self.__macro().setEnv('NeXusMeshScanID', serial)
202
+ return serial
156
203
 
157
204
  def __command(self, server, command, *args):
158
205
  """ execute tango server (or python object) command
@@ -326,10 +373,12 @@ class NXS_FileRecorder(BaseFileRecorder):
326
373
 
327
374
  :param filename: sardana scanfile name
328
375
  :type filename: :obj:`str`
329
- :param numer: True if append scanID
330
- :param numer: :obj:`bool`
376
+ :param number: True if append scanID
377
+ :param number: :obj:`bool`
331
378
  :param scanID: scanID to append
332
379
  :type scanID: :obj:`int`
380
+ :returns: True if append scanID
381
+ :rtype: :obj:`bool`
333
382
  """
334
383
  if scanID is not None and scanID < 0:
335
384
  return number
@@ -358,20 +407,26 @@ class NXS_FileRecorder(BaseFileRecorder):
358
407
 
359
408
  subs = (len([None for _ in list(re.finditer('%', filename))]) == 1)
360
409
  # construct the filename, e.g. : /dir/subdir/etcdir/prefix_00123.nxs
361
- if subs or number:
362
- if scanID is None:
363
- serial = self.recordlist.getEnvironValue('serialno')
364
- elif scanID >= 0:
365
- if isarver >= 304 or isarver == 0:
366
- serial = scanID
367
- else:
368
- serial = scanID + 1
410
+ self.__serial = self._serial(scanID)
411
+
369
412
  if subs:
370
413
  try:
371
414
  #: output file name
372
- self.filename = filename % serial
415
+ self.filename = filename % self.__serial
373
416
  except Exception:
374
417
  subs = False
418
+ if not self.__raw_filename:
419
+ self.__raw_filename = self.__rawfilename(self.__serial)
420
+ self.debug('__setFileName: '
421
+ 'Raw Filename: %s' % str(self.__raw_filename))
422
+ if not subs and self.__raw_filename and \
423
+ "{ScanID" in self.__raw_filename:
424
+ try:
425
+ self.filename = self.__raw_filename.format(
426
+ ScanID=self.__serial)
427
+ subs = True
428
+ except Exception:
429
+ pass
375
430
 
376
431
  if not subs:
377
432
  if number:
@@ -379,10 +434,12 @@ class NXS_FileRecorder(BaseFileRecorder):
379
434
  filename[-4].rpartition(".")[0] and \
380
435
  filename[-4].rpartition(".")[2] in self.formats.keys():
381
436
  tpl = filename[-4].rpartition(".")
382
- self.filename = "%s_%05d.%s.tmp" % (tpl[0], serial, tpl[2])
437
+ self.filename = "%s_%05d.%s.tmp" % (
438
+ tpl[0], self.__serial, tpl[2])
383
439
  else:
384
440
  tpl = filename.rpartition('.')
385
- self.filename = "%s_%05d.%s" % (tpl[0], serial, tpl[2])
441
+ self.filename = "%s_%05d.%s" % (
442
+ tpl[0], self.__serial, tpl[2])
386
443
  else:
387
444
  self.filename = filename
388
445
 
@@ -403,6 +460,9 @@ class NXS_FileRecorder(BaseFileRecorder):
403
460
  profile configuration of NXSRecSelector
404
461
  :type onlyconfig: :obj:`bool`
405
462
  """
463
+ self.debug(
464
+ '__setNexusDevices: NXSRecSelector: %s'
465
+ % str(self.__raw_filename))
406
466
  vl = self.__getEnvVar("NeXusSelectorDevice", None)
407
467
  if vl is None:
408
468
  servers = self.__db.get_device_exported_for_class(
@@ -424,6 +484,8 @@ class NXS_FileRecorder(BaseFileRecorder):
424
484
  "Cannot connect to '%s'" % servers[0])
425
485
  else:
426
486
  self.__nexussettings_device = None
487
+ self.debug('__setNexusDevices: import profile: %s'
488
+ % str(self.__raw_filename))
427
489
  if self.__nexussettings_device is None:
428
490
  from nxsrecconfig import Settings
429
491
  self.__nexussettings_device = Settings.Settings()
@@ -433,10 +495,13 @@ class NXS_FileRecorder(BaseFileRecorder):
433
495
  raise Exception("NXSRecSelector (%s) version below 2.0.0" %
434
496
  (servers[0] if servers else "module"))
435
497
 
498
+ self.debug('__setNexusDevices: set MG: %s' % str(self.__raw_filename))
436
499
  mntgrp = self.__getServerVar("mntGrp", None)
437
500
  amntgrp = self.__getEnvVar("ActiveMntGrp", None)
438
501
  if mntgrp and amntgrp != mntgrp:
439
502
  self.__nexussettings_device.mntgrp = amntgrp
503
+ self.debug('__setNexusDevices: list profile: %s'
504
+ % str(self.__raw_filename))
440
505
  if amntgrp not in self.__command(
441
506
  self.__nexussettings_device, "availableProfiles"):
442
507
  if onlyconfig:
@@ -457,15 +522,29 @@ class NXS_FileRecorder(BaseFileRecorder):
457
522
  self.info(
458
523
  "NXS_FileRecorer: descriptive components will be reset")
459
524
  else:
525
+ self.debug('__setNexusDevices: fetch profile: %s'
526
+ % str(self.__raw_filename))
460
527
  self.__command(self.__nexussettings_device, "fetchProfile")
528
+ self.debug('__setNexusDevices: reset profile: %s'
529
+ % str(self.__raw_filename))
461
530
  self.__asynchcommand(self.__nexussettings_device,
462
531
  "resetPreselectedComponents")
532
+ self.debug('__setNexusDevices: reset profile Done: %s'
533
+ % str(self.__raw_filename))
463
534
  self.__oddmntgrp = True
464
535
  else:
536
+ self.debug('__setNexusDevices: '
537
+ 'fetch profile 2: %s' % str(self.__raw_filename))
465
538
  self.__command(self.__nexussettings_device, "fetchProfile")
539
+ self.debug('__setNexusDevices: fetch profile 2 Done: %s' %
540
+ str(self.__raw_filename))
466
541
  self.__vars["vars"]["measurement_group"] = amntgrp
467
542
 
543
+ self.debug('__setNexusDevices: '
544
+ 'profile config: %s' % str(self.__raw_filename))
468
545
  self.__conf = self.__getServerVar("profileConfiguration", {}, True)
546
+ self.debug('__setNexusDevices: '
547
+ 'MG config: %s' % str(self.__raw_filename))
469
548
  if not self.__oddmntgrp and not onlyconfig:
470
549
  if "MntGrpConfiguration" in self.__conf.keys():
471
550
  poolmg = self.__command(
@@ -475,9 +554,9 @@ class NXS_FileRecorder(BaseFileRecorder):
475
554
  poolmg = None
476
555
  profmg = None
477
556
  if not poolmg or not profmg or poolmg != profmg:
478
- self.debug(
479
- "ActiveMntGrp created outside NXSRecSelector v3. "
480
- "Updating ActiveMntGrp")
557
+ self.debug("__setNexusDevices: "
558
+ "ActiveMntGrp created outside NXSRecSelector v3. "
559
+ "Updating ActiveMntGrp")
481
560
  if self.__macro:
482
561
  self.__macro().debug(
483
562
  "ActiveMntGrp created outside NXSRecSelector v3. "
@@ -485,6 +564,8 @@ class NXS_FileRecorder(BaseFileRecorder):
485
564
  self.__command(self.__nexussettings_device, "importMntGrp")
486
565
  self.__command(self.__nexussettings_device, "updateMntGrp")
487
566
 
567
+ self.debug('__setNexusDevices: '
568
+ 'Writer Device: %s' % str(self.__raw_filename))
488
569
  if not onlyconfig:
489
570
  vl = self.__getConfVar("WriterDevice", None)
490
571
  if not vl:
@@ -510,9 +591,24 @@ class NXS_FileRecorder(BaseFileRecorder):
510
591
  else:
511
592
  self.__nexuswriter_device = None
512
593
 
594
+ self.debug('__setNexusDevices: Writer Device Properties: %s'
595
+ % str(self.__raw_filename))
513
596
  if self.__nexuswriter_device is None:
514
597
  from nxswriter import TangoDataWriter
515
598
  self.__nexuswriter_device = TangoDataWriter.TangoDataWriter()
599
+ try:
600
+ properties = dict(
601
+ self.__getEnvVar("NeXusWriterProperties", {}))
602
+ except Exception as e:
603
+ self.warning(
604
+ "Cannot load NeXusWriterProperties %s" % (str(e)))
605
+ self.__macro().warning(
606
+ "Cannot load NeXusWriterProperties %s" % (str(e)))
607
+ properties = {}
608
+ for ky, vl in properties.items():
609
+ if hasattr(self.__nexuswriter_device, ky):
610
+ setattr(self.__nexuswriter_device, ky, vl)
611
+ self.debug('__setNexusDevices: End: %s' % str(self.__raw_filename))
516
612
 
517
613
  def __get_alias(self, name):
518
614
  """ provides a device alias
@@ -538,6 +634,26 @@ class NXS_FileRecorder(BaseFileRecorder):
538
634
  alias = None
539
635
  return alias
540
636
 
637
+ def __short_name(self, name):
638
+ """ provides a device alias
639
+
640
+ :param name: device name
641
+ :type name: :obj:`str`
642
+ :returns: device alias
643
+ :rtype: :obj:`str`
644
+ """
645
+ # if name does not contain a "/" it's probably an alias
646
+ if name.startswith("tango://"):
647
+ name = name[8:]
648
+ if name.find("/") == -1:
649
+ return name
650
+
651
+ # haso107klx:10000/expchan/hasysis3820ctrl/1
652
+ if name.find(':') >= 0:
653
+ lst = name.split("/")
654
+ name = "/".join(lst[1:])
655
+ return name
656
+
541
657
  def __collectAliases(self, envRec):
542
658
  """ sets deviceAlaises and dynamicDataSources from env record
543
659
 
@@ -575,22 +691,30 @@ class NXS_FileRecorder(BaseFileRecorder):
575
691
  else:
576
692
  self.__dynamicDataSources[(str(elm.name))] = None
577
693
 
578
- def __createDynamicComponent(self, dss, keys, nexuscomponents):
694
+ def __createDynamicComponent(self, dss, keys, udata, nexuscomponents):
579
695
  """ creates a dynamic component
580
696
 
581
697
  :param dss: datasource list
582
698
  :type dss: :obj:`list` <:obj:`str`>
583
699
  :param keys: keys without datasources
584
700
  :type keys: :obj:`list` <:obj:`str`>
701
+ :param udata: keys without datasources
702
+ :type udata: :obj:`dict` <:obj:`str`, `any`>
585
703
  :param nexuscomponents: nexus component list
586
704
  :type nexuscomponents: :obj:`list` <:obj:`str`>
587
705
  """
588
- self.debug("Step DSs: %s" % dss)
589
- self.debug("Init DSs: %s" % keys)
706
+ self.debug("__createDynamicComponent: Step DSs: %s" % dss)
707
+ self.debug("__createDynamicComponent: Init DSs: %s" % keys)
708
+ self.debug("__createDynamicComponent: Init User Data: %s" % udata)
590
709
  envRec = self.recordlist.getEnviron()
591
710
  lddict = []
592
711
  tdss = [ds for ds in dss if not ds.startswith("tango://")
593
712
  and ds not in nexuscomponents]
713
+ tgdss = [self.__short_name(ds)
714
+ for ds in dss if ds.startswith("tango://")
715
+ and ds not in nexuscomponents]
716
+
717
+ fields = []
594
718
  for dd in envRec['datadesc']:
595
719
  alias = self.__get_alias(str(dd.name))
596
720
  if alias in tdss and alias not in nexuscomponents:
@@ -598,11 +722,56 @@ class NXS_FileRecorder(BaseFileRecorder):
598
722
  mdd["name"] = dd.name
599
723
  mdd["shape"] = dd.shape
600
724
  mdd["dtype"] = dd.dtype
725
+ mdd["strategy"] = 'STEP'
601
726
  lddict.append(mdd)
727
+
728
+ fields = {}
729
+ for ky, vl in udata.items():
730
+ if "@" not in ky:
731
+ mdd = {}
732
+ mdd["name"] = ky
733
+ mdd["shape"] = numpy.shape(vl)
734
+ try:
735
+ if mdd["shape"]:
736
+ rank = len(mdd["shape"])
737
+ for _ in range(rank):
738
+ vl = vl[0]
739
+ mdd["dtype"] = str(type(vl).__name__)
740
+ except Exception as e:
741
+ self.warning("Cannot find a type of user data %s %s"
742
+ % (ky, str(e)))
743
+ self.__macro().warning(
744
+ "Cannot find a type of user data %s %s" % (ky, str(e)))
745
+ mdd["dtype"] = 'string'
746
+ mdd["strategy"] = 'INIT'
747
+ fields[ky] = mdd
748
+
749
+ for ky, vl in udata.items():
750
+ if "@" in ky:
751
+ fld, att = ky.split("@")[:2]
752
+ if fld and att:
753
+ if fld in fields.keys():
754
+ fields[fld][att] = vl
755
+ else:
756
+ fields[fld] = {
757
+ "name": fld,
758
+ "dtype": "string",
759
+ "shape": tuple(),
760
+ att: vl}
761
+
762
+ for mdd in fields.values():
763
+ lddict.append(mdd)
764
+
765
+ tdss.extend(tgdss)
602
766
  jddict = json.dumps(lddict, cls=NXS_FileRecorder.numpyEncoder)
603
767
  jdss = json.dumps(tdss, cls=NXS_FileRecorder.numpyEncoder)
604
768
  jkeys = json.dumps(keys, cls=NXS_FileRecorder.numpyEncoder)
605
- # self.debug("JDD: %s" % jddict)
769
+ self.debug("__createDynamicComponent: "
770
+ "tango STEP datasources: %s" % tdss)
771
+ self.debug("__createDynamicComponent: "
772
+ "sardana STEP datasources: %s" % jddict)
773
+ self.debug("__createDynamicComponent: "
774
+ "INIT datasources: %s" % jkeys)
606
775
  self.__dynamicCP = \
607
776
  self.__command(self.__nexussettings_device,
608
777
  "createDynamicComponent",
@@ -646,6 +815,8 @@ class NXS_FileRecorder(BaseFileRecorder):
646
815
  :rtype: (`list` <:obj:`str`>, `list` <:obj:`str`>,
647
816
  `list` <:obj:`str`>, `list` <:obj:`str`>)
648
817
  """
818
+ self.debug("__searchDataSources: Init: %s"
819
+ % str([nexuscomponents, cfm, dyncp, userkeys]))
649
820
  dsFound = {}
650
821
  dsNotFound = []
651
822
 
@@ -661,6 +832,8 @@ class NXS_FileRecorder(BaseFileRecorder):
661
832
  else:
662
833
  cmps = list(set(nexuscomponents) &
663
834
  set(self.__availableComponents()))
835
+ self.debug("__searchDataSources: Get selected DSs: %s"
836
+ % str([cfm, dyncp]))
664
837
  if self.__oddmntgrp:
665
838
  nds = []
666
839
  else:
@@ -668,15 +841,27 @@ class NXS_FileRecorder(BaseFileRecorder):
668
841
  "selectedDataSources")
669
842
  nds = nds if nds else []
670
843
  datasources = list(set(nds) | set(self.__deviceAliases.keys()))
844
+ self.debug("__searchDataSources: Get components DSs: %s"
845
+ % str([cfm, dyncp]))
671
846
  hascpsrcs = hasattr(self.__nexussettings_device, 'componentSources')
847
+ # aacpdss = json.loads(
848
+ # self.__command(self.__nexussettings_device,
849
+ # "componentSources",
850
+ # cmps))
851
+ self.debug("__searchDataSources: component loop: %s"
852
+ % str([cfm, dyncp]))
672
853
  for cp in cmps:
854
+ self.debug("__searchDataSources: component item: %s" % cp)
673
855
  try:
674
856
  if hascpsrcs:
675
857
  cpdss = json.loads(
676
858
  self.__command(self.__nexussettings_device,
677
859
  "componentSources",
678
860
  [cp]))
679
- allcpdss.extend([ds["dsname"] for ds in cpdss])
861
+ allcpdss.extend(
862
+ [ds["dsname"] for ds in cpdss
863
+ if ("parentobj" not in ds or
864
+ ds["parentobj"] in ["field"])])
680
865
 
681
866
  else:
682
867
  cpdss = json.loads(
@@ -698,28 +883,38 @@ class NXS_FileRecorder(BaseFileRecorder):
698
883
  "Component '%s' wrongly defined in DB!" % cp)
699
884
  # self.__macro().warning("Error: '%s'" % str(e))
700
885
  else:
701
- self.debug("Component '%s' wrongly defined in DB!" % cp)
886
+ self.debug(
887
+ "__searchDataSources: "
888
+ "Component '%s' wrongly defined in DB!" % cp)
702
889
  self.warning("Error: '%s'" % str(e))
703
890
  if self.__macro:
704
891
  self.__macro().debug(
892
+ "__searchDataSources: "
705
893
  "Component '%s' wrongly defined in DB!" % cp)
706
894
  self.__macro.debug("Error: '%s'" % str(e))
707
895
  dss = []
708
896
  if dss:
709
897
  cdss = list(set(dss) & set(datasources))
710
898
  for ds in cdss:
711
- self.debug("'%s' found in '%s'" % (ds, cp))
899
+ self.debug("__searchDataSources: '%s' found in '%s'"
900
+ % (ds, cp))
712
901
  if ds not in dsFound.keys():
713
902
  dsFound[ds] = []
714
903
  dsFound[ds].append(cp)
715
904
  if cp not in cpReq.keys():
716
905
  cpReq[cp] = []
717
906
  cpReq[cp].append(ds)
907
+ self.debug("__searchDataSources: "
908
+ "component loop end: %s" % str([cfm, dyncp]))
718
909
  missingKeys = set(userkeys) - keyFound
719
910
 
911
+ self.debug("__searchDataSources: "
912
+ "dynamic component loop: %s" % str([cfm, dyncp]))
720
913
  datasources.extend(self.__dynamicDataSources.keys())
721
914
  #: get not found datasources
722
915
  for ds in datasources:
916
+ self.debug("__searchDataSources: "
917
+ " dynamic component item: %s" % ds)
723
918
  if ds not in dsFound.keys() and ds not in allcpdss:
724
919
  dsNotFound.append(ds)
725
920
  if not dyncp:
@@ -748,6 +943,8 @@ class NXS_FileRecorder(BaseFileRecorder):
748
943
  "It was not found in User Components!"
749
944
  " Consider setting: "
750
945
  "NeXusDynamicComponents=True" % ds)
946
+ self.debug("__searchDataSources: "
947
+ "dynamic component loop end: %s" % str([cfm, dyncp]))
751
948
  return (nds, dsNotFound, cpReq, list(missingKeys))
752
949
 
753
950
  def __createConfiguration(self, userdata):
@@ -758,14 +955,19 @@ class NXS_FileRecorder(BaseFileRecorder):
758
955
  :returns: configuration xml string
759
956
  :rtype: :obj:`str`
760
957
  """
958
+ self.debug("__createConfiguration: Init: %s" % self.__oddmntgrp)
761
959
  cfm = self.__getConfVar("ComponentsFromMntGrp",
762
960
  False, pass_default=self.__oddmntgrp)
763
961
  dyncp = self.__getConfVar("DynamicComponents",
764
962
  True, pass_default=self.__oddmntgrp)
765
963
 
766
964
  envRec = self.recordlist.getEnviron()
965
+ self.debug("__createConfiguration: CollectAllises: %s"
966
+ % self.__oddmntgrp)
767
967
  self.__collectAliases(envRec)
768
968
 
969
+ self.debug("__createConfiguration: Get Components: %s"
970
+ % self.__oddmntgrp)
769
971
  mandatory = self.__command(self.__nexussettings_device,
770
972
  "mandatoryComponents")
771
973
  self.info("Default Components %s" % str(mandatory))
@@ -787,13 +989,19 @@ class NXS_FileRecorder(BaseFileRecorder):
787
989
  self.info("Available Components %s" % str(
788
990
  self.__availableComponents()))
789
991
 
992
+ self.debug("__createConfiguration: Search DataSources: %s"
993
+ % self.__oddmntgrp)
790
994
  nds, dsNotFound, cpReq, missingKeys = self.__searchDataSources(
791
995
  list(set(nexuscomponents) | set(mandatory)),
792
996
  cfm, dyncp, userdata.keys())
793
-
794
- self.debug("DataSources Not Found : %s" % dsNotFound)
795
- self.debug("Components required : %s" % cpReq)
796
- self.debug("Missing User Data : %s" % missingKeys)
997
+ self.debug("__createConfiguration: Get User data: %s"
998
+ % self.__oddmntgrp)
999
+
1000
+ self.debug("__createConfiguration: DataSources Not Found : %s"
1001
+ % dsNotFound)
1002
+ self.debug("__createConfiguration: Components required : %s" % cpReq)
1003
+ self.debug("__createConfiguration: Missing User Data : %s"
1004
+ % missingKeys)
797
1005
  if "InitDataSources" in self.__conf.keys():
798
1006
  # compatibility with version 2
799
1007
  ids = self.__getConfVar(
@@ -804,12 +1012,20 @@ class NXS_FileRecorder(BaseFileRecorder):
804
1012
  "DataSourcePreselection",
805
1013
  None, True, pass_default=self.__oddmntgrp)
806
1014
  ids = [k for (k, vl) in idsdct.items() if vl] if idsdct else None
807
- if ids:
808
- missingKeys.extend(list(ids))
809
- self.__vars["vars"]["nexus_init_datasources"] = " ".join(missingKeys)
1015
+ self.__vars["vars"]["nexus_init_datasources"] = \
1016
+ " ".join(missingKeys + list(ids or []))
1017
+ udata = {str(re.sub('[^0-9a-zA-Z@_]+', "_", str(ky))): userdata[ky]
1018
+ for ky in missingKeys}
1019
+ # udata = {ky: userdata[ky] for ky in missingKeys}
1020
+ if userdata:
1021
+ userdata.update(udata)
1022
+ self.debug("__createConfiguration: Create dynamic components: %s"
1023
+ % self.__oddmntgrp)
810
1024
  self.__createDynamicComponent(
811
- dsNotFound if dyncp else [], missingKeys, nexuscomponents)
1025
+ dsNotFound if dyncp else [], ids or [], udata, nexuscomponents)
812
1026
  nexuscomponents.append(str(self.__dynamicCP))
1027
+ self.debug("__createConfiguration: Add Components: %s"
1028
+ % self.__oddmntgrp)
813
1029
 
814
1030
  if cfm:
815
1031
  self.info("Sardana Components %s" % cpReq.keys())
@@ -839,6 +1055,11 @@ class NXS_FileRecorder(BaseFileRecorder):
839
1055
  self.__aliases = [ch for ch in och if ch in allcp]
840
1056
  if self.__aliases:
841
1057
  self.__vars["vars"]["mgchannels"] = " ".join(self.__aliases)
1058
+ timers = self.__command(self.__nexussettings_device,
1059
+ "availableTimers")
1060
+ if timers:
1061
+ self.__vars["vars"]["timers"] = " ".join(timers)
1062
+
842
1063
  self.__vars["vars"]["nexus_components"] = " ".join(nexuscomponents)
843
1064
  stepdss = [str(ds) for ds in envRec['ref_moveables']
844
1065
  if str(ds) in toswitch]
@@ -852,25 +1073,38 @@ class NXS_FileRecorder(BaseFileRecorder):
852
1073
  if self.__macro:
853
1074
  self.__macro().debug(
854
1075
  "VAR %s" % self.__nexussettings_device.configVariables)
1076
+ self.debug("__createConfiguration: Update Config Varialels: %s"
1077
+ % self.__oddmntgrp)
855
1078
  self.__command(self.__nexussettings_device,
856
1079
  "updateConfigVariables")
857
1080
 
858
- self.debug("Aliases: %s" % str(self.__aliases))
859
- self.debug("Switching to STEP mode: %s" % stepdss)
1081
+ self.debug("__createConfiguration: Aliases: %s"
1082
+ % str(self.__aliases))
1083
+ self.debug("__createConfiguration: Switching to STEP mode: %s"
1084
+ % stepdss)
860
1085
  oldtoswitch = self.__getServerVar("stepdatasources", "[]", False)
861
1086
  stepdss = str(json.dumps(list(toswitch)))
1087
+ self.debug("__createConfiguration: Set STEP datasources: %s"
1088
+ % self.__oddmntgrp)
862
1089
  self.__nexussettings_device.stepdatasources = stepdss
1090
+ self.debug("__createConfiguration: Set LINK datasources: %s"
1091
+ % self.__oddmntgrp)
863
1092
  if hasattr(self.__nexussettings_device, "linkdatasources"):
864
1093
  self.__nexussettings_device.linkdatasources = stepdss
1094
+ self.debug("__createConfiguration: "
1095
+ "Create Writer configuration: %s" % self.__oddmntgrp)
865
1096
  cnfxml = self.__command(
866
1097
  self.__nexussettings_device, "createWriterConfiguration",
867
1098
  nexuscomponents)
868
1099
  finally:
1100
+ self.debug("__createConfiguration: Reset variables: %s"
1101
+ % self.__oddmntgrp)
869
1102
  self.__nexussettings_device.configVariables = json.dumps(
870
1103
  nexusvariables)
871
1104
  if oldtoswitch is not None:
872
1105
  self.__nexussettings_device.stepdatasources = oldtoswitch
873
1106
 
1107
+ self.debug("__createConfiguration: End: %s" % self.__oddmntgrp)
874
1108
  return cnfxml
875
1109
 
876
1110
  def _startRecordList(self, recordlist):
@@ -881,49 +1115,89 @@ class NXS_FileRecorder(BaseFileRecorder):
881
1115
  :type recordlist: :class:`sardana.macroserver.scan.scandata.RecordList`
882
1116
  """
883
1117
  try:
1118
+ self.debug('_startRecordList: Start %s' % self.__base_filename)
884
1119
  self.__env = self.__macro().getAllEnv() if self.__macro else {}
885
1120
  if self.__base_filename is None:
886
1121
  return
1122
+ self.__udata = None
887
1123
 
1124
+ self.debug('_startRecordList: Set NeXus %s'
1125
+ % self.__base_filename)
888
1126
  self.__setNexusDevices()
1127
+ self.debug('_startRecordList: Set Variables %s'
1128
+ % self.__base_filename)
889
1129
 
890
1130
  appendentry = self.__getConfVar("AppendEntry", True)
891
-
892
- appendentry = not self.__setFileName(
1131
+ appendscanid = not self.__setFileName(
893
1132
  self.__base_filename, not appendentry)
894
1133
  envRec = self.recordlist.getEnviron()
895
- self.__vars["vars"]["serialno"] = envRec["serialno"] \
896
- if appendentry else ""
1134
+ self.__vars["vars"]["serialno"] = ("_%05i" % self.__serial) \
1135
+ if appendscanid else ""
897
1136
  self.__vars["vars"]["scan_id"] = envRec["serialno"]
1137
+ self.__vars["vars"]["acq_modes"] = \
1138
+ ",".join(self.writerModes or [])
898
1139
  self.__vars["vars"]["scan_title"] = envRec["title"]
1140
+ if self.__macro:
1141
+ if hasattr(self.__macro(), "integ_time"):
1142
+ self.__vars["vars"]["count_time"] = \
1143
+ self.__macro().integ_time
1144
+ if hasattr(self.__macro(), "nb_points"):
1145
+ self.__vars["vars"]["npoints"] = \
1146
+ self.__macro().nb_points
1147
+ self.__vars["vars"]["beamtime_id"] = self.beamtimeid()
899
1148
  tzone = self.__getConfVar("TimeZone", self.__timezone)
900
1149
  self.__vars["data"]["start_time"] = \
901
1150
  self.__timeToString(envRec['starttime'], tzone)
902
1151
  self.__vars["vars"]["filename"] = str(self.filename)
903
1152
 
904
1153
  envrecord = self.__appendRecord(self.__vars, 'INIT')
1154
+ self.debug('_startRecordList: Create Configuration %s'
1155
+ % self.__base_filename)
1156
+ cnfxml = self.__createConfiguration(envrecord["data"])
1157
+ self.debug('_startRecordList: Set Remove dynamic components %s'
1158
+ % self.__base_filename)
905
1159
  rec = json.dumps(
906
1160
  envrecord, cls=NXS_FileRecorder.numpyEncoder)
907
- cnfxml = self.__createConfiguration(envrecord["data"])
908
1161
  # self.debug('XML: %s' % str(cnfxml))
909
1162
  self.__removeDynamicComponent()
910
1163
 
911
- self.__vars["data"]["serialno"] = envRec["serialno"]
1164
+ self.__vars["data"]["serialno"] = self.__serial
912
1165
  self.__vars["data"]["scan_title"] = envRec["title"]
913
-
1166
+ if self.__macro:
1167
+ if hasattr(self.__macro(), "integ_time"):
1168
+ self.__vars["data"]["count_time"] = \
1169
+ self.__macro().integ_time
1170
+ if hasattr(self.__macro(), "nb_points"):
1171
+ self.__vars["data"]["npoints"] = \
1172
+ self.__macro().nb_points
1173
+ self.__vars["data"]["beamtime_id"] = \
1174
+ self.__vars["vars"]["beamtime_id"]
1175
+
1176
+ self.debug('_startRecordList: Init writer %s'
1177
+ % self.__base_filename)
914
1178
  if hasattr(self.__nexuswriter_device, 'Init'):
915
1179
  self.__command(self.__nexuswriter_device, "Init")
916
1180
  self.__nexuswriter_device.fileName = str(self.filename)
917
1181
  self.__command(self.__nexuswriter_device, "openFile")
918
1182
  self.__nexuswriter_device.xmlsettings = cnfxml
919
1183
 
920
- # self.debug('START_DATA: %s' % str(envRec))
1184
+ if "DEBUG_INIT_DATA" in self.writerModes:
1185
+ self.debug('_startRecordList: INIT_DATA: %s' % str(envRec))
921
1186
 
1187
+ self.debug('_startRecordList: Set JSON %s' % self.__base_filename)
922
1188
  self.__nexuswriter_device.jsonrecord = rec
1189
+ self.writerModes = self.__variableList(
1190
+ "NeXusWriterModes")
1191
+ if "NOINIT" in self.writerModes:
1192
+ self.__nexuswriter_device.skipAcquisition = True
1193
+
1194
+ self.debug('_startRecordList SE: Open Entry %s' %
1195
+ self.__base_filename)
923
1196
  self.__command(self.__nexuswriter_device, "openEntry")
924
1197
  except Exception:
925
1198
  self.__removeDynamicComponent()
926
1199
  raise
1200
+ self.debug('_startRecordList SE: END %s' % self.__base_filename)
927
1201
 
928
1202
  def __appendRecord(self, var, mode=None):
929
1203
  """ merges userdata with variable dictionary
@@ -945,6 +1219,38 @@ class NXS_FileRecorder(BaseFileRecorder):
945
1219
  dct = self.__getConfVar("UserData", None, True)
946
1220
  if isinstance(dct, dict):
947
1221
  nexusrecord = dct
1222
+
1223
+ ms = None
1224
+ msf = None
1225
+ if not isinstance(self.__udata, dict):
1226
+ if 'MetadataScript' in self.__env.keys():
1227
+ msf = self.__env['MetadataScript']
1228
+ # elif 'FioAdditions' in self.__env.keys():
1229
+ # msf = self.__env['FioAdditions']
1230
+ if msf:
1231
+ if not os.path.exists(msf):
1232
+ self.warning("NXS_FileRecorder: %s does not exist" % msf)
1233
+ if self.__macro:
1234
+ self.__macro().warning(
1235
+ "NXS_FileRecorder: %s does not exist" % msf)
1236
+ else:
1237
+ import importlib.util
1238
+ spec = importlib.util.spec_from_file_location('', msf)
1239
+ msm = importlib.util.module_from_spec(spec)
1240
+ spec.loader.exec_module(msm)
1241
+ ms = msm.main()
1242
+ if not isinstance(ms, dict):
1243
+ self.warning(
1244
+ "NXS_FileRecorder: bad output from %s" % msf)
1245
+ if self.__macro:
1246
+ self.__macro().warning(
1247
+ "NXS_FileRecorder: bad output from %s" % msf)
1248
+ self.__udata = {}
1249
+ else:
1250
+ self.__udata = ms
1251
+ if isinstance(self.__udata, dict) and isinstance(ms, dict):
1252
+ nexusrecord.update(self.__udata)
1253
+
948
1254
  record = dict(var)
949
1255
  record["data"] = dict(var["data"], **nexusrecord)
950
1256
  if mode == 'INIT':
@@ -974,10 +1280,13 @@ class NXS_FileRecorder(BaseFileRecorder):
974
1280
  rec = json.dumps(
975
1281
  envrecord, cls=NXS_FileRecorder.numpyEncoder)
976
1282
  self.__nexuswriter_device.jsonrecord = rec
1283
+ if "NOSTEP" in self.writerModes:
1284
+ self.__nexuswriter_device.skipAcquisition = True
977
1285
 
978
- # self.debug('DATA: {"data":%s}' % json.dumps(
979
- # record.data,
980
- # cls=NXS_FileRecorder.numpyEncoder))
1286
+ if "DEBUG_STEP_DATA" in self.writerModes:
1287
+ self.debug('_writeRecord DATA: {"data":%s}' % json.dumps(
1288
+ record.data,
1289
+ cls=NXS_FileRecorder.numpyEncoder))
981
1290
 
982
1291
  jsonString = '{"data":%s}' % json.dumps(
983
1292
  record.data,
@@ -998,8 +1307,16 @@ class NXS_FileRecorder(BaseFileRecorder):
998
1307
  :returns: formatted time string
999
1308
  :rtype: :obj:`str`
1000
1309
  """
1310
+ fmt = '%Y-%m-%dT%H:%M:%S.%f%z'
1001
1311
  try:
1002
- tz = pytz.timezone(tzone)
1312
+ if sys.version_info >= (3, 9):
1313
+ import zoneinfo
1314
+ tz = zoneinfo.ZoneInfo(tzone)
1315
+ starttime = mtime.replace(tzinfo=tz)
1316
+ else:
1317
+ import pytz
1318
+ tz = pytz.timezone(tzone)
1319
+ starttime = tz.localize(mtime)
1003
1320
  except Exception:
1004
1321
  self.warning(
1005
1322
  "Wrong TimeZone. "
@@ -1008,10 +1325,15 @@ class NXS_FileRecorder(BaseFileRecorder):
1008
1325
  self.__macro().warning(
1009
1326
  "Wrong TimeZone. "
1010
1327
  "The time zone set to `%s`" % self.__timezone)
1011
- tz = pytz.timezone(self.__timezone)
1328
+ if sys.version_info >= (3, 9):
1329
+ import zoneinfo
1330
+ tz = zoneinfo.ZoneInfo(self.__timezone)
1331
+ starttime = mtime.replace(tzinfo=tz)
1332
+ else:
1333
+ import pytz
1334
+ tz = pytz.timezone(self.__timezone)
1335
+ starttime = tz.localize(mtime)
1012
1336
 
1013
- fmt = '%Y-%m-%dT%H:%M:%S.%f%z'
1014
- starttime = tz.localize(mtime)
1015
1337
  return str(starttime.strftime(fmt))
1016
1338
 
1017
1339
  def _endRecordList(self, recordlist):
@@ -1028,7 +1350,8 @@ class NXS_FileRecorder(BaseFileRecorder):
1028
1350
  self.__env = self.__macro().getAllEnv() if self.__macro else {}
1029
1351
  envRec = recordlist.getEnviron()
1030
1352
 
1031
- # self.debug('END_DATA: %s ' % str(envRec))
1353
+ if "DEBUG_FINAL_DATA" in self.writerModes:
1354
+ self.debug('_endRecordList: FINAL_DATA: %s ' % str(envRec))
1032
1355
 
1033
1356
  tzone = self.__getConfVar("TimeZone", self.__timezone)
1034
1357
  self.__vars["data"]["end_time"] = \
@@ -1039,6 +1362,8 @@ class NXS_FileRecorder(BaseFileRecorder):
1039
1362
  rec = json.dumps(
1040
1363
  envrecord, cls=NXS_FileRecorder.numpyEncoder)
1041
1364
  self.__nexuswriter_device.jsonrecord = rec
1365
+ if "NOFINAL" in self.writerModes:
1366
+ self.__nexuswriter_device.skipAcquisition = True
1042
1367
  self.__command(self.__nexuswriter_device, "closeEntry")
1043
1368
  self.__command(self.__nexuswriter_device, "closeFile")
1044
1369
  except Exception:
@@ -1048,6 +1373,9 @@ class NXS_FileRecorder(BaseFileRecorder):
1048
1373
  vl = self.__getEnvVar("NXSAppendSciCatDataset", None)
1049
1374
  if vl:
1050
1375
  self.__appendSciCatDataset(vl)
1376
+ cmf = self.__getEnvVar("CreateMeasurementFile", False)
1377
+ if cmf and NXSWRITER:
1378
+ self.__createMeasurementFile()
1051
1379
 
1052
1380
  def beamtime_id(self, bmtfpath, bmtfprefix, bmtfext):
1053
1381
  """ code for beamtimeid datasource
@@ -1063,29 +1391,108 @@ class NXS_FileRecorder(BaseFileRecorder):
1063
1391
  """
1064
1392
  result = ""
1065
1393
  fpath = self.filename
1066
- if fpath.startswith(bmtfpath):
1067
- try:
1394
+ try:
1395
+ if fpath.startswith(bmtfpath):
1068
1396
  if os.path.isdir(bmtfpath):
1069
1397
  btml = [fl for fl in os.listdir(bmtfpath)
1070
1398
  if (fl.startswith(bmtfprefix)
1071
1399
  and fl.endswith(bmtfext))]
1072
1400
  result = btml[0][len(bmtfprefix):-len(bmtfext)]
1401
+ except Exception:
1402
+ pass
1403
+ return result
1404
+
1405
+ def beamtimeid(self):
1406
+ bmtfpath = self.__getEnvVar("BeamtimeFilePath", "/gpfs/current")
1407
+ bmtfprefix = self.__getEnvVar(
1408
+ "BeamtimeFilePrefix", "beamtime-metadata-")
1409
+ bmtfext = self.__getEnvVar("BeamtimeFileExt", ".json")
1410
+ beamtimeid = self.beamtime_id(bmtfpath, bmtfprefix, bmtfext)
1411
+ return beamtimeid or "00000000"
1412
+
1413
+ def __variableList(self, variable='NeXusWriterModes'):
1414
+ """ read variable list
1415
+ """
1416
+ try:
1417
+ msvar = self.__macro().getEnv(variable)
1418
+ except Exception:
1419
+ msvar = []
1420
+ if isinstance(msvar, str):
1421
+ msvar = re.split(r"[-;,.\s]\s*", msvar)
1422
+ if msvar:
1423
+ self.debug('__variableList: %s: %s' % (variable, str(msvar)))
1424
+ return msvar
1425
+
1426
+ def __rawfilename(self, serial):
1427
+ """ find scan name
1428
+ """
1429
+ try:
1430
+ scan_file = self.__macro().getEnv('ScanFile')
1431
+ except Exception:
1432
+ scan_file = []
1433
+ try:
1434
+ scan_dir = self.__macro().getEnv('ScanDir')
1435
+ except Exception:
1436
+ scan_dir = "/"
1437
+ if isinstance(scan_file, str):
1438
+ scan_file = [scan_file]
1439
+ bfilename = ""
1440
+
1441
+ for sfile in scan_file:
1442
+ sfile = os.path.join(scan_dir, sfile)
1443
+ try:
1444
+ ffile = sfile.format(ScanID=serial)
1445
+ except KeyError:
1446
+ ffile = sfile
1447
+ if ffile == self.__base_filename:
1448
+ bfilename = sfile
1449
+ break
1450
+ bfilename = bfilename or self.__base_filename
1451
+ return bfilename
1452
+
1453
+ def __scanname(self, serial, default=None):
1454
+ """ find scan name
1455
+ """
1456
+ if not self.__raw_filename:
1457
+ self.__raw_filename = self.__rawfilename(serial)
1458
+ if default:
1459
+ return default
1460
+ bfilename = self.__raw_filename
1461
+ _, bfname = os.path.split(bfilename)
1462
+ if bfname.endswith(".tmp"):
1463
+ bfname = bfname[:-4]
1464
+ sname, fext = os.path.splitext(bfname)
1465
+ scanname = os.path.commonprefix(
1466
+ [sname.format(ScanID=11111111),
1467
+ sname.format(ScanID=99999999)])
1468
+ if '%' in scanname:
1469
+ try:
1470
+ scanname = os.path.commonprefix(
1471
+ [scanname % 11111111,
1472
+ scanname % 99999999])
1073
1473
  except Exception:
1074
1474
  pass
1075
- return result
1475
+ if scanname.endswith("_"):
1476
+ scanname = scanname[:-1]
1477
+ return scanname
1076
1478
 
1077
1479
  def __appendSciCatDataset(self, hostname=None):
1078
1480
  """ append dataset to SciCat ingestion list """
1079
1481
 
1482
+ sid = self.__serial
1080
1483
  fdir, fname = os.path.split(self.filename)
1484
+ snmode = self.__getEnvVar("ScanNames", None)
1485
+ nometa = self.__getEnvVar("ScanNamesNoMetadata", False)
1486
+ nogrouping = self.__getEnvVar("ScanNamesNoGrouping", False)
1487
+ appendentry = self.__getConfVar("AppendEntry", False)
1488
+ pdir = None
1489
+ if snmode is not None:
1490
+ if bool(snmode):
1491
+ fdir = os.path.dirname(os.path.abspath(fdir))
1492
+ elif appendentry is False:
1493
+ fdir, pdir = os.path.split(os.path.abspath(fdir))
1081
1494
  sname, fext = os.path.splitext(fname)
1082
-
1083
- bmtfpath = self.__getEnvVar("BeamtimeFilePath", "/gpfs/current")
1084
- bmtfprefix = self.__getEnvVar(
1085
- "BeamtimeFilePrefix", "beamtime-metadata-")
1086
- bmtfext = self.__getEnvVar("BeamtimeFileExt", ".json")
1087
- beamtimeid = self.beamtime_id(bmtfpath, bmtfprefix, bmtfext)
1088
- beamtimeid = beamtimeid or "00000000"
1495
+ beamtimeid = self.beamtimeid()
1089
1496
  defprefix = "scicat-datasets-"
1090
1497
  defaulthost = self.__getEnvVar("SciCatDatasetListFileLocal", None)
1091
1498
  if defaulthost:
@@ -1097,8 +1504,131 @@ class NXS_FileRecorder(BaseFileRecorder):
1097
1504
  dslfile = "%s%s%s" % (dslprefix, beamtimeid, dslext)
1098
1505
  if fdir:
1099
1506
  dslfile = os.path.join(fdir, dslfile)
1100
- with open(dslfile, "a+") as fl:
1101
- fl.write("\n%s" % sname)
1507
+
1508
+ entryname = "scan"
1509
+ appendentry = self.__getConfVar("AppendEntry", False)
1510
+ variables = self.__getConfVar("ConfigVariables", None, True)
1511
+ if isinstance(variables, dict) and "entryname" in variables:
1512
+ entryname = variables["entryname"]
1513
+
1514
+ scanname = self.__scanname(sid, pdir)
1515
+ # _, bfname = os.path.split(self.__base_filename)
1516
+ # try:
1517
+ # scanname, _ = os.path.splitext(bfname % "")
1518
+ # except Exception:
1519
+ # scanname, _ = os.path.splitext(bfname)
1520
+
1521
+ if appendentry is True and \
1522
+ '%' not in self.__raw_filename and \
1523
+ "{ScanID" not in self.__raw_filename:
1524
+ sid = self.__serial
1525
+ sname = "%s::/%s_%05i;%s_%05i" % (
1526
+ scanname, entryname, sid, scanname, sid)
1527
+ if pdir:
1528
+ sname = "%s/%s" % (pdir, sname)
1529
+ if "NOINIT" in self.writerModes:
1530
+ sname = "%s:%s" % (sname, time.time())
1531
+
1532
+ # auto grouping
1533
+ grouping = bool(self.__getEnvVar('SciCatAutoGrouping', False))
1534
+
1535
+ if grouping or pdir:
1536
+ commands = []
1537
+ try:
1538
+ sm = dict(self.__getEnvVar('SciCatMeasurements', {}))
1539
+ if not isinstance(sm, dict):
1540
+ sm = {}
1541
+ except Exception:
1542
+ sm = {}
1543
+
1544
+ if fdir in sm.keys():
1545
+ cgrp = sm[fdir]
1546
+ if cgrp != scanname:
1547
+ if not nogrouping and not nometa:
1548
+ commands.append("__command__ stop")
1549
+ commands.append("%s:%s" % (cgrp, time.time()))
1550
+ commands.append("__command__ start %s" % scanname)
1551
+ else:
1552
+ if not nogrouping and not nometa:
1553
+ commands.append("__command__ start %s" % scanname)
1554
+ if not nometa:
1555
+ commands.append(sname)
1556
+ if not nogrouping and not nometa:
1557
+ commands.append("__command__ stop")
1558
+ if not nogrouping:
1559
+ commands.append("%s:%s" % (scanname, time.time()))
1560
+ sname = "\n".join(commands)
1561
+
1562
+ if not nogrouping and not nometa:
1563
+ sm[fdir] = scanname
1564
+ self.__env['SciCatMeasurements'] = sm
1565
+
1566
+ if sname:
1567
+ with open(dslfile, "a+") as fl:
1568
+ fl.write("\n%s" % sname)
1569
+
1570
+ def __createMeasurementFile(self):
1571
+ """ create measurement file """
1572
+
1573
+ sid = self.__serial
1574
+ fdir, fname = os.path.split(self.filename)
1575
+ pdir = None
1576
+ snmode = self.__getEnvVar("ScanNames", None)
1577
+ appendentry = self.__getConfVar("AppendEntry", False)
1578
+ if snmode is not None:
1579
+ if bool(snmode):
1580
+ fdir = os.path.dirname(os.path.abspath(fdir))
1581
+ elif appendentry is False:
1582
+ fdir, pdir = os.path.split(os.path.abspath(fdir))
1583
+ sname, fext = os.path.splitext(fname)
1584
+ # beamtimeid = self.beamtimeid()
1585
+
1586
+ scanname = self.__scanname(sid, pdir)
1587
+ # _, bfname = os.path.split(self.__base_filename)
1588
+ # try:
1589
+ # scanname, _ = os.path.splitext(bfname % "")
1590
+ # except Exception:
1591
+ # scanname, _ = os.path.splitext(bfname)
1592
+
1593
+ try:
1594
+ sm = dict(self.__getEnvVar('SciCatMeasurements', {}))
1595
+ if not isinstance(sm, dict):
1596
+ sm = {}
1597
+ except Exception:
1598
+ sm = {}
1599
+
1600
+ entryname = "scan"
1601
+ appendentry = self.__getConfVar("AppendEntry", False)
1602
+ variables = self.__getConfVar("ConfigVariables", None, True)
1603
+ if isinstance(variables, dict) and "entryname" in variables:
1604
+ entryname = variables["entryname"]
1605
+ if appendentry is True:
1606
+ if '%' not in self.__raw_filename and \
1607
+ "{ScanID" not in self.__raw_filename:
1608
+ sname = sname + ("_%05i" % sid)
1609
+ entryname = entryname + ("_%05i" % sid)
1610
+ mntname = scanname
1611
+ if fdir in sm.keys() and sm[fdir]:
1612
+ mntname = sm[fdir]
1613
+ if not appendentry or mntname != scanname:
1614
+ mntfile = os.path.join(fdir, mntname + fext)
1615
+
1616
+ if not os.path.exists(mntfile):
1617
+ fl = h5writer.create_file(mntfile)
1618
+ self.info("Measurement file '%s' created " % mntname)
1619
+ else:
1620
+ fl = h5writer.open_file(mntfile, readonly=False)
1621
+ rt = fl.root()
1622
+ if sname not in rt.names():
1623
+ if pdir:
1624
+ h5writer.link("%s/%s:/%s" %
1625
+ (pdir, fname, entryname), rt, sname)
1626
+ else:
1627
+ h5writer.link("%s:/%s" % (fname, entryname), rt, sname)
1628
+ self.debug("__createMeasurementFile: "
1629
+ "Link '%s' in '%s' created " % (sname, mntname))
1630
+ rt.close()
1631
+ fl.close()
1102
1632
 
1103
1633
  def _addCustomData(self, value, name, group="data", remove=False,
1104
1634
  **kwargs):
@@ -1,6 +0,0 @@
1
- sardananxsrecorder/__init__.py,sha256=XdJ1vBb5H1uB31VjKJM3emVnHEFtPzRmGHnuRyECfeY,896
2
- sardananxsrecorder/nxsrecorder.py,sha256=zsQI4aTchCtmJMtVl0vaU6Oyp-lHrMOlqg3ALUaaPPI,44518
3
- sardana_nxsrecorder-3.13.2.dist-info/METADATA,sha256=ovBaBnwlE6a68yFUYl4I8CDENgd-H90GZl5qOJYcwP8,6993
4
- sardana_nxsrecorder-3.13.2.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
5
- sardana_nxsrecorder-3.13.2.dist-info/top_level.txt,sha256=YdD3m417i-jlYyQWgiizgZ8lQQcOjM8y-bmUHrGkfY4,19
6
- sardana_nxsrecorder-3.13.2.dist-info/RECORD,,