# -*- coding: utf-8 -*-
# This software and supporting documentation are distributed by
# Institut Federatif de Recherche 49
# CEA/NeuroSpin, Batiment 145,
# 91191 Gif-sur-Yvette cedex
# France
#
# This software is governed by the CeCILL license version 2 under
# French law and abiding by the rules of distribution of free software.
# You can use, modify and/or redistribute the software under the
# terms of the CeCILL license version 2 as circulated by CEA, CNRS
# and INRIA at the following URL "http://www.cecill.info".
#
# As a counterpart to the access to the source code and rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty and the software's author, the holder of the
# economic rights, and the successive licensors have only limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading, using, modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also
# therefore means that it is reserved for developers and experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and, more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license version 2 and that you accept its terms.
"""
This module defines the class :py:class:`ReadDiskItem` which is a subclass :py:class:`brainvisa.data.neuroData.Parameter`.
It is used to define an input data file as a parameter in a :py:class:`brainvisa.processes.Process` :py:class:`brainvisa.data.neuroData.Signature`.
"""
from __future__ import print_function
from __future__ import absolute_import
import os
import operator
# from soma.debug import print_stack
from soma.path import split_query_string
from soma.undefined import Undefined
from brainvisa.data.neuroData import Parameter
from brainvisa.processes import getDiskItemType
import brainvisa.processes
from brainvisa.data.neuroDiskItems import getFormat, getFormats, DiskItem, isSameDiskItemType, File, Directory
from brainvisa.processing.neuroException import HTMLMessage
import six
import sys
from functools import reduce
#----------------------------------------------------------------------------
def diskItemFilter(database, diskItem, required, explainRejection=False):
if diskItem.type is not None:
types = database.getTypeChildren(
*database.getAttributeValues('_type', {}, required))
if types and diskItem.type.name not in types:
if explainRejection:
return 'DiskItem type ' + repr(diskItem.type.name) + ' is not in ' + repr(tuple(types))
return False
formats = database.getAttributeValues('_format', {}, required)
if formats and diskItem.format is not None:
if diskItem.format.name not in formats:
if explainRejection:
if diskItem.format is None:
value = None
else:
value = diskItem.format.name
return 'DiskItem format ' + repr(value) + ' is not in ' + repr(tuple(formats))
return False
for key in required:
if key in ('_type', '_format', '_declared_attributes_location'):
continue
values = database.getAttributeValues(key, {}, required)
itemValue = diskItem.get(key, '')
if (key == 'name_serie'):
if itemValue != values:
if explainRejection:
return 'DiskItem attribute ' + repr(key) + ' = ' + repr(itemValue) + ' != ' + repr(values)
return False
else:
if itemValue not in values:
if explainRejection:
return 'DiskItem attribute ' + repr(key) + ' = ' + repr(itemValue) + ' is not in ' + repr(tuple(values))
return False
return True
#----------------------------------------------------------------------------
[docs]class ReadDiskItem(Parameter):
"""
The expected value for this parameter must be a readable :py:class:`brainvisa.data.neuroDiskItems.DiskItem`.
This parameter type uses BrainVISA data organization to select possible files.
:Syntax:
::
ReadDiskItem( file_type_name, formats [, required_attributes, enableConversion=1, ignoreAttributes=0 ])
formats <- format_name
formats <- [ format_name, ... ]
required_attributes <- { name : value, ...}
file_type_name enables to select files of a specific type, that is to say DiskItem objects whose type is either file_name_type or a derived type. The formats list gives the exhaustive list of accepted formats for this parameter. But if there are some converters ( see the section called “Role”) from other formats to one of the accepted formats, they will be accepted too because BrainVISA can automatically convert the parameter (if enableConversion value is 1, which is the default). Warning : the type and formats given in parameters of ReadDiskItem constructor must have been defined in BrainVISA types and hierarchies files. required_attributes enables to add some conditions on the parameter value : it will have to match the given attributes value.
This method of files selection ease file selection by showing the user only files that matches type and format required for this parameter. It also enables BrainVISA to automatically fill some parameters values. The ReadDiskItem class has methods to search matching diskitems in BrainVISA databases :
* :py:meth:`ReadDiskItem.findItems(\<database directory diskitem\> <ReadDiskItem.findItems>`, <attributes>) : this method returns a list of diskitems that exist in that database and match type, format and required attributes of the parameter. It is possible to specify additional attributes in the method parameters. Found items will have the selected value for these attributes if they have the attribute, but these attributes are not mandatory. That's the difference with the required attributes set in the constructor.
* :py:meth:`ReadDiskItem.findValues(\<value\>) <ReadDiskItem.findValues>` : this method searches diskitems matching the value in parameter. This value can be a diskitem, a filename, a dictionary of attributes.
* :py:meth:`ReadDiskItem.findValue(\<value\>) <ReadDiskItem.findValue>` : this method returns the best among possible value, that is to say with the more common attributes, highest priority. If there is an ambiguity, it returns None.
**Examples**
>>> ReadDiskItem( 'Volume 3D', [ 'GIS Image', 'VIDA image' ] )
>>> ReadDiskItem( 'Cortical folds graph', 'Graph', requiredAttributes = { 'labelled' : 'No', 'side' : 'left'} )
In the first example, the parameter will accept only a file whose type is 3D Volume and format is either GIS image or VIDA image, or a format that can be converted to GIS or VIDA image. These types and formats must have been defined first. In the second example, the parameter value type must be "Cortical folds graph", its format must be "Graph". The required attributes add some conditions : the graph isn't labelled and represents the left hemisphere.
"""
def __init__(self, diskItemType, formats, requiredAttributes={},
enableConversion=True, ignoreAttributes=False, _debug=None,
exactType=False, section=None, enableMultiResolution=False ):
Parameter.__init__(self, section)
self._debug = _debug
self.type = getDiskItemType(diskItemType)
formatsList = list(getFormats(formats))
if len(formatsList) != 0:
self.formats = (formatsList[0], ) + tuple(sorted(formatsList))
else:
self.formats = ()
self.enableConversion = enableConversion
self.exactType = exactType
self.enableMultiResolution = enableMultiResolution
self._formatsWithConversion = None
self.requiredAttributes = requiredAttributes
self._write = False
# self._modified = 0
self.ignoreAttributes = ignoreAttributes
self._selectedAttributes = {}
self.valueLinkedNotifier.add(self.valueLinked)
_formatsAndConversionCache = {}
def _getDatabase(self):
'''Returns the database this disk item belongs to
'''
# WARNING: don't import earlier to prevent a circular inclusion!
from brainvisa.data import neuroHierarchy
return neuroHierarchy.databases
database = property(_getDatabase)
# Allow direct affectation to requiredAttributes for backward compatibility
def _getRequiredAttributes(self):
#_debug = self._debug
# if _debug is not None:
# print('!_getRequiredAttributes!', self, self.type, self.formats,
# self.enableConversion, file=_debug)
if self._requiredAttributes['_format'] is None:
cache = self._formatsAndConversionCache.get(
(self.type.name, self.formats))
# if _debug is not None:
# print('!_getRequiredAttributes! 1', cache, file=_debug)
if cache is None:
formats = set(self.database.formats.getFormat(
f.name, f).name for f in self.formats)
# if _debug is not None:
# print('!_getRequiredAttributes! 2', formats, file=_debug)
formatsWithConversion = set()
any = getDiskItemType('Any type')
for f in getFormats(self.formats):
convs = brainvisa.processes.getConvertersTo(
(any, f), checkUpdate=False)
convs.update(brainvisa.processes.getConvertersTo(
(self.type, f), keepType=0, checkUpdate=False))
# if _debug is not None:
# print('!_getRequiredAttributes! 3', self.type,
# object.__repr__( self.type ), f, object.__repr__( f ),
# convs, file=_debug)
for type_format, converter in six.iteritems(convs):
typ, format = type_format
formatName = self.database.formats.getFormat(
format.name, format).name
# if _debug is not None:
# print('!_getRequiredAttributes! 4', formatName,
# file=_debug)
if formatName not in formats:
formatsWithConversion.add(formatName)
cache = (formats, formatsWithConversion)
self._formatsAndConversionCache[
(self.type.name, self.formats)] = cache
formats, self._formatsWithConversion = cache
# if _debug is not None:
# print('!_getRequiredAttributes! 5', formats,
# self._formatsWithConversion, file=_debug)
if self.enableConversion:
self._requiredAttributes['_format'] = self._formatsWithConversion.union(
formats)
else:
self._requiredAttributes['_format'] = formats
self._requiredAttributes['_type'] = self.type.name
# if _debug is not None:
# print('!_getRequiredAttributes! 6', self._requiredAttributes[
# '_format' ], file=_debug)
return self._requiredAttributes
def _setRequiredAttributes(self, value):
self._requiredAttributes = value.copy()
self._requiredAttributes['_type'] = self.type.name
self._requiredAttributes['_format'] = None
requiredAttributes = property(
_getRequiredAttributes, _setRequiredAttributes)
[docs] def valueLinked(self, parameterized, name, value):
"""This method is a callback called when the valueLinkedNotifier is activated.
This notifier is shared between this parameter and the initial parameter in the static signature of the process.
So when this function is called self is the initial parameter in the static signature.
That why self is not used in this function.
"""
if isinstance(value, DiskItem):
parameterized.signature[
name]._selectedAttributes = value.hierarchyAttributes()
elif isinstance(value, dict):
parameterized.signature[name]._selectedAttributes = value
else:
parameterized.signature[name]._selectedAttributes = {}
[docs] def checkValue(self, name, value):
Parameter.checkValue(self, name, value)
if ((value is not None) and (self.mandatory == True)):
if not value.isReadable():
raise RuntimeError(
HTMLMessage(_t_('the parameter <em>%s</em> is not readable or does not exist : %s') % (six.text_type(name), six.text_type(value))))
def get_formats_order(self, database_dir):
if database_dir in (None, ''):
return self.formats
from brainvisa.configuration import neuroConfig
dbs = [d for d in neuroConfig.dataPath
if d.directory == database_dir]
if len(dbs) != 1:
return self.formats
dbs = dbs[0]
forder = getattr(dbs.expert_settings, 'preferred_formats_order',
None)
if forder is None:
return self.formats
fdict = {}
for f in self.formats: # TODO: could use a cache for this dict
fdict[f.name] = f
hprio = [fdict[f] for f in forder if f in fdict]
lprio = [f for f in self.formats if f not in hprio]
return hprio + lprio
[docs] def findValue(self, selection, requiredAttributes=None,
preferExisting=False, ignore_db_formats_sorting=False,
_debug=Undefined):
'''Find the best matching value for the ReadDiskItem, according to the given selection criterions.
The "best matching" criterion is the maximum number of common attributes with the selection, with required attributes satisfied.
In case of WriteDiskItem, if preferExisting, also search for value already in database.
If there is an ambiguity (no matches, or several equivalent matches), *None* is returned.
Parameters
----------
selection: diskitem, or dictionary, or str (filename)
requiredAttributes: dictionary (optional)
preferExisting: boolean
ignore_db_formats_sorting: boolean
by default, in Axon >= 4.6.2, formats are sorted according to
database-specific formats orders, thus overriding process-specified
formats orders. This flag allows to disable this behavior.
_debug: file-like object (optional)
Returns
-------
matching_value: :py:class:`DiskItem <brainvisa.data.neuroDiskItems.DiskItem>` instance, or *None*
'''
if _debug is Undefined:
_debug = self._debug
if selection is None:
return None
if requiredAttributes is None:
requiredAttributes = self.requiredAttributes
else:
r = self.requiredAttributes.copy()
r.update(requiredAttributes)
requiredAttributes = r
if _debug is not None:
print('\n' + '-' * 70, file=_debug)
print(self.__class__.__name__ +
'(\'' + str(self.type) + '\').findValue', file=_debug)
if isinstance(selection, DiskItem):
print(' value type = DiskItem', file=_debug)
print(' fullPath = ', repr(selection), file=_debug)
print(' type = ', repr(selection.type), file=_debug)
print(' format = ', repr(selection.format), file=_debug)
print(' attributes:', file=_debug)
for n, v in selection.attributes().items():
print(' ', n, '=', repr(v), file=_debug)
else:
print(' value type =', type(selection), file=_debug)
print(' value = ', selection, file=_debug)
print(' required attributes:', file=_debug)
for n, v in six.iteritems(requiredAttributes):
print(' ', n, '=', repr(v), file=_debug)
# print('- ' * 35, file=_debug)
# print_stack( file=_debug )
# print('- ' * 35, file=_debug)
result = None
fullSelection = None
write = False
if isinstance(selection, DiskItem):
if selection.getHierarchy('_database') is None:
# If DiskItem is not in a database, required attributes are
# ignored (except _format)
rr = {}
if '_format' in requiredAttributes:
rr['_format'] = requiredAttributes['_format']
requiredAttributes = rr
if (selection.type is None or (selection.type is self.type) or
(not self.exactType and (isSameDiskItemType( selection.type, self.type ) or isSameDiskItemType( self.type, selection.type )))) \
and self.diskItemFilter(selection, requiredAttributes):
result = selection
else:
if _debug is not None:
print(' DiskItem rejected because:', self.diskItemFilter(
selection, requiredAttributes, explainRejection=True), file=_debug)
if selection._write:
if _debug is not None:
print(
' DiskItem has the _write attribute set to True',
file=_debug)
write = True
fullSelection = selection.globalAttributes()
if selection.type is None:
fullSelection['_type'] = None
else:
fullSelection['_type'] = selection.type.name
if selection.format is None:
fullSelection['_format'] = None
else:
fullSelection['_format'] = selection.format.name
elif isinstance(selection, six.string_types):
if selection.startswith('{'):
# String value is a dictionary
return self.findValue(eval(selection), requiredAttributes=requiredAttributes, _debug=_debug)
fullSelection = None
if selection == '':
return None # avoid using cwd
selection, query_string = split_query_string(selection)
fileName = os.path.normpath(os.path.abspath(selection))
for database in self.database.iterDatabases():
if fileName.startswith(database.directory + os.sep):
break
else:
database = self.database
result = database.getDiskItemFromFileName(
fileName + query_string, None)
if result is None:
if _debug is not None:
print(' DiskItem not found in databases', file=_debug)
directory = getFormat('Directory') in self.formats
result = database.createDiskItemFromFileName(
fileName + query_string, None, directory=directory)
if result is None:
if _debug is not None:
print(
' DiskItem not created in databases from file name',
file=_debug)
# WARNING FIXME QUESTION ??
# Denis 2018/08/07
# createDiskItemFromFileName() 3 lines earlier already
# calls createDiskItemFromFormatExtension(), so if we
# are here, createDiskItemFromFormatExtension can just not
# work, right ?
result = database.createDiskItemFromFormatExtension(
fileName + query_string, None)
if result is None:
if _debug is not None:
print(
' DiskItem not created in databases from format extension',
file=_debug)
if os.path.exists( fileName ):
from brainvisa.tools.aimsGlobals import aimsFileInfo
file_type = aimsFileInfo(fileName).get('file_type')
if _debug is not None:
print(
' aimsFileInfo returned file_type =', repr(
file_type),
file=_debug)
if file_type == 'DICOM':
if _debug is not None:
print(
' creating DICOM DiskItem', file=_debug)
result = File(fileName + query_string, None)
result.format = getFormat('DICOM image')
result.type = None
result._files = [fileName]
result.readAndUpdateMinf()
else:
result.readAndUpdateMinf()
else:
result.readAndUpdateMinf()
if _debug is not None:
print(' DiskItem created in databases', file=_debug)
if result is None:
if _debug is not None:
print(
' no format found for file name extension', file=_debug)
directoryFormat = getFormat('Directory')
if directoryFormat in self.formats:
# In this case, item is a directory
if _debug is not None:
print(
' no extension ==> create Directory item', file=_debug)
result = Directory(fileName + query_string, None)
result.format = directoryFormat
result._files = [fileName]
result._identified = False
result.type = self.type
result.readAndUpdateMinf()
elif _debug is not None:
print(
' found matching format:', result.format, file=_debug)
elif _debug is not None:
print(' DiskItem found in databases', file=_debug)
if result is not None:
if result.type is None:
# Set the result type if this is not already done
result.type = self.type
if result.getHierarchy('_database') is None:
# If DiskItem is not in a database, required attributes are
# ignored
requiredAttributes = {
'_format': requiredAttributes.get('_format')}
# if the diskitem format does not match the required
# format, and if required format contains Series of
# diskitem.format, try to change the format of the diskItem
# to a format series.
if not self.diskItemFilter(result, requiredAttributes):
if ("Series of " + result.format.name in requiredAttributes.get("_format")):
database.changeDiskItemFormatToSeries(result)
if not self.diskItemFilter(result, requiredAttributes):
if _debug is not None:
print(' DiskItem rejected because:', self.diskItemFilter(
result, requiredAttributes, explainRejection=True), file=_debug)
result = None
if result is None and self._parameterized is not None \
and self._name is not None \
and not self._parameterized().isDefault(self._name):
try:
result = database.createDiskItemFromFormatExtension(
selection + query_string)
if result is not None:
result.type = self.type
except Exception:
pass
elif isinstance(selection, dict):
if '_declared_attributes_location' in list(selection.keys()):
# keep it could cause problems because it should not be
# compared between disk items
del selection['_declared_attributes_location']
else:
pass
fullSelection = dict(selection)
if result is None and fullSelection is not None:
values = []
if preferExisting and (write or self._write):
fullAttributes = fullSelection.copy()
fullAttributes.update(requiredAttributes)
values = list(self._findValues(fullSelection, fullAttributes,
write=False,
_debug=_debug))
if not values:
values = list(self._findValues(fullSelection, requiredAttributes,
write=(write or self._write),
_debug=_debug))
if values:
if len(values) == 1:
result = values[0]
else:
# Find the item with the "smallest" "distance" from item
values = sorted((self.diskItemDistance(i, selection), i)
for i in values)
if _debug is not None:
print(' findValue priority sorted items:', file=_debug)
print('dist to:',
selection.attributes() if isinstance(selection, DiskItem) else selection,
file=_debug)
for l in values:
print(' ', l, l[1].attributes(), file=_debug)
if values[0][0] != values[1][0]:
result = values[0][1]
else:
refOrder, refDiskItem = values[0]
refHierarchy = refDiskItem.hierarchyAttributes()
# WARNING: this _declared_attributes_location attribute causes
# problems since it should not be compared between disk
# items
try:
del refHierarchy['_declared_attributes_location']
except KeyError:
pass
differentOnFormatOnly = [refDiskItem]
for checkOrder, checkDiskItem in values[1:]:
if checkOrder != refOrder:
break
checkHierarchy = checkDiskItem.hierarchyAttributes(
)
# WARNING: this _declared_attributes_location attribute causes
# problems since it should not be compared between
# disk items
try:
del checkHierarchy[
'_declared_attributes_location']
except KeyError:
pass
if ((refHierarchy == checkHierarchy) and (refDiskItem.format.name != checkDiskItem.format.name)):
differentOnFormatOnly.append(checkDiskItem)
else:
differentOnFormatOnly = []
break
if differentOnFormatOnly:
formatsToTest = self.get_formats_order(
differentOnFormatOnly[0].getHierarchy(
'_database'))
for preferredFormat in formatsToTest:
l = [
i for i in differentOnFormatOnly if i.format is preferredFormat]
if l:
result = l[0]
break
if _debug is not None:
print(
' top priority values differ only by formats:',
file=_debug)
for i in differentOnFormatOnly:
print(' ', i.format, file=_debug)
if result:
print(
' chosen format:', result.format, file=_debug)
elif _debug is not None:
print(
' top priority values differ on ontology attributes ==> no selection on format', file=_debug)
print(
'ref element:', refDiskItem.fullPath(), refHierarchy, file=_debug)
print(
'check element:', checkDiskItem.fullPath(), checkHierarchy, file=_debug)
# this block of code was originally in WriteDiskItem.findValue().
# We do not remember what it was exactly meant for, and did not do
# correctly its job. We don't completely remove it because it might solve
# a very specific situation, but we also fix it: check requiredAttributes,
# and select preferred format instead of the first one.
# (Denis 2015/10/09)
if result is None and write and isinstance( selection, DiskItem ) and \
(selection.type is None or selection.type is self.type
or (not self.exactType
and isSameDiskItemType(selection.type, self.type))):
format = requiredAttributes.get('_format') or self.formats[0]
if _debug is not None:
print(
' No unique best selection found. But compatible input DiskItem. Checking format.', file=_debug)
print(' Format:', format, file=_debug)
if format in self.formats and format != selection.format:
# check requiredAttributes
sel_attr = selection.hierarchyAttributes()
ok = True
for attrib, value in six.iteritems(requiredAttributes):
if not attrib.startswith('_') and \
(attrib not in sel_attr or sel_attr[attrib] != value):
ok = False
break
if _debug:
print(' checking RequiredAttributes:', ok, file=_debug)
if ok:
result = self.database.changeDiskItemFormat(
selection, format.name)
if _debug is not None:
print(
' selection is compatible with a different format, select: %s'
% format, file=_debug)
if _debug is not None:
print('-> findValue return', result, file=_debug)
if result is not None:
print('-> type:', result.type, file=_debug)
print('-> format:', result.format, file=_debug)
print('-> attributes:', file=_debug)
for n, v in result.attributes().items():
print('-> ', n, '=', v, file=_debug)
print('-' * 70 + '\n', file=_debug)
_debug.flush()
return result
[docs] def diskItemDistance(self, diskItem, other):
'''Returns a value that represents a sort of distance between two
DiskItems.
The distance is not a number but distances can be sorted.'''
# Count the number of common hierarchy attributes
if isinstance(other, DiskItem):
if other.type is not None:
other_type = other.type.name
else:
other_type = None
other_priority = other.priority()
else:
other_type = other.get('_type')
other_priority = 0
if diskItem.type is not None:
diskItem_type = diskItem.type.name
else:
diskItem_type = None
if isinstance(other, DiskItem):
getHierarchy = other.getHierarchy
getNonHierarchy = other.getNonHierarchy
else:
getHierarchy = other.get
getNonHierarchy = other.get
filtered_out_attribs = set(
['_ontology', '_declared_attributes_location'])
hierarchyCommon = reduce(
operator.add,
((getHierarchy(n) == v)
for n, v in six.iteritems(diskItem.hierarchyAttributes())
if n not in filtered_out_attribs),
(int(diskItem_type == other_type)))
# Count the number of common non hierarchy attributes
nonHierarchyCommon = reduce(
operator.add,
((getNonHierarchy(n) == v)
for n, v in six.iteritems(diskItem.nonHierarchyAttributes())),
(int(diskItem_type == other_type)))
if getattr(other, '_write', False) and diskItem.isReadable():
readable = -1
else:
readable = 0
return (-hierarchyCommon, other_priority - diskItem.priority(), -nonHierarchyCommon, readable)
[docs] def findValues(self, selection, requiredAttributes={}, write=False,
_debug=Undefined):
'''Find all DiskItems matching the selection criterions
Parameters
----------
selection: :py:class:`DiskItem <brainvisa.data.neuroDiskItems.DiskItem>` or dictionary
requiredAttributes: dictionary (optional)
write: bool (optional)
if write is True, look for write diskitems
_debug: file-like object (optional)
'''
return self._findValues(selection, requiredAttributes, write, _debug)
def _findValues(self, selection, requiredAttributes, write, _debug=Undefined):
if _debug is Undefined:
_debug = self._debug
if requiredAttributes is None:
requiredAttributes = self.requiredAttributes
keySelection = {}
if selection:
# in selection attributes, choose only key attributes because the
# request must not be too restrictive to avoid failure. The results
# will be sorted by distance to the selection later.
keyAttributes = self.database.getTypesKeysAttributes(
self.type.name)
keySelection = dict((i, selection[i]) for i in keyAttributes
if i in selection)
# type is required in database selection
if '_type' not in keySelection:
keySelection['_type'] = self.type.name
readValues = (i for i in self.database.findDiskItems(
keySelection, _debug=_debug, exactType=self.exactType,
write=self._write, **requiredAttributes)
if self.diskItemFilter(i, requiredAttributes))
if write:
# use selection attributes to create a new diskitem
fullPaths = set()
for item in readValues:
fullPaths.add(item.fullPath())
yield item
requiredAttributes = dict(requiredAttributes) # copy
if '_type' not in requiredAttributes:
# if selection is a diskitem with a different type as self
requiredAttributes['_type'] = self.type.name
if '_format' not in requiredAttributes:
requiredAttributes['_format'] = self.formats
# Do not allow formats that require a conversion in DiskItem
# creation
if self._formatsWithConversion:
oldFormats = requiredAttributes.get('_format')
if oldFormats is not None:
requiredAttributes['_format'] = [
i for i in oldFormats if i not in self._formatsWithConversion]
for item in self.database.createDiskItems(selection, _debug=_debug, exactType=self.exactType, **requiredAttributes):
if self.diskItemFilter(item, requiredAttributes):
if item.fullPath() not in fullPaths:
yield item
elif _debug is not None:
print(' ', item, 'rejected because:', self.diskItemFilter(
item, requiredAttributes, explainRejection=True), file=_debug)
if self._formatsWithConversion:
requiredAttributes['_format'] = oldFormats
else:
for i in readValues:
yield i
def diskItemFilter(self, *args, **kwargs):
return diskItemFilter(self.database, *args, **kwargs)
# if diskItem.type is not None:
# types = self.database.getTypeChildren( *self.database.getAttributeValues( '_type', {}, required ) )
# if types and diskItem.type.name not in types:
# if explainRejection:
# return 'DiskItem type ' + repr(diskItem.type.name) + ' is not in ' + repr( tuple(types) )
# return False
# formats = self.database.getAttributeValues( '_format', {}, required )
# if formats and not(diskItem.format is None) :
# if diskItem.format.name not in formats:
# if explainRejection:
# if diskItem.format is None :
# value = None
# else :
# value = diskItem.format.name
# return 'DiskItem format ' + repr(value) + ' is not in ' + repr( tuple(formats) )
# return False
# for key in required:
# if key in ( '_type', '_format' ): continue
# values = self.database.getAttributeValues( key, {}, required )
# itemValue = diskItem.get( key, Undefined )
# if itemValue is Undefined or itemValue not in values:
# if explainRejection:
# if itemValue is Undefined:
# return 'DiskItem do not have the required ' + repr( key ) + ' attribute'
# else:
# return 'DiskItem attribute ' + repr(key) + ' = ' + repr( itemValue ) + ' is not in ' + repr( tuple(values) )
# return False
# return True
[docs] def typeInfo(self, translator=None):
if translator:
translate = translator.translate
else:
translate = _t_
formats = ''
for f in self.formats:
if formats:
formats += ', '
formats += translate(f.name)
return ((translate('Type'), translate(self.type.name)),
(translate('Access'), translate('input')),
(translate('Formats'), formats))
[docs] def toolTipText(self, parameterName, documentation):
result = '<center>' + parameterName
if not self.mandatory:
result += ' (' + _t_('optional') + ')'
result += '</center><hr><b>' + _t_( 'Type' ) + \
':</b> ' + self.type.name + '<br><b>' + _t_( 'Formats' ) + \
':</b><blockquote>'
br = 0
for f in self.formats:
if br:
result += '<br>'
else:
br = 1
result += f.name + ': ' + str(f.getPatterns().patterns[0].pattern)
result += '</blockquote><b>' + _t_( 'Description' ) + '</b>:<br>' + \
documentation
return result
[docs] def editor(self, parent, name, context):
# WARNING: don't import at the beginning of the module,
# it would cause a circular inclusion
from brainvisa.data.qtgui.readdiskitemGUI import DiskItemEditor
return DiskItemEditor(self, parent, name, context=context,
write=self._write,
process=getattr(context, 'parameterized', None))
[docs] def listEditor(self, parent, name, context):
# WARNING: don't import at the beginning of the module,
# it would cause a circular inclusion
from brainvisa.data.qtgui.readdiskitemGUI import DiskItemListEditor
return DiskItemListEditor(self, parent, name, context=context,
write=self._write,
process=getattr(context, 'parameterized', None))