class OpenPMDRawDataReader(RawDataReaderBase): def __init__(self, location, speciesName, dataName, internalName, firstTimeStep): # Store an openPMD timeseries object # (Its API is used in order to conveniently extract data from the file) self.openpmd_ts = OpenPMDTimeSeries(location, check_all_files=False) # Initialize the instance RawDataReaderBase.__init__(self, location, speciesName, dataName, internalName, firstTimeStep) def _ReadData(self, timeStep): data, = self.openpmd_ts.get_particle([self.internalName], species=self.speciesName, iteration=timeStep) self.currentTime = self._ReadTime(timeStep) return data def _ReadTime(self, timeStep): # The line below sets the attribute `_current_i` of openpmd_ts self.openpmd_ts._find_output(None, timeStep) # This sets the corresponding time self.currentTime = self.openpmd_ts.t[self.openpmd_ts._current_i] def _ReadUnits(self): # OpenPMD data always provide conversion to SI units self.dataUnits = "" # TODO: self.timeUnits = "s" def _OpenFile(self, timeStep): # The line below sets the attribute `_current_i` of openpmd_ts self.openpmd_ts._find_output(None, timeStep) # This finds the full path to the corresponding file fileName = self.openpmd_ts.h5_files[self.openpmd_ts._current_i] file_content = H5File(fileName, 'r') return file_content
class OpenPMDRawDataReader(RawDataReaderBase): def __init__(self, location, speciesName, dataName, internalName, firstTimeStep): # First check whether openPMD is installed if not openpmd_installed: raise RunTimeError("You need to install openPMD-viewer, e.g. with:\n" "pip install openPMD-viewer") # Store an openPMD timeseries object # (Its API is used in order to conveniently extract data from the file) self.openpmd_ts = OpenPMDTimeSeries( location, check_all_files=False ) # Initialize the instance RawDataReaderBase.__init__(self, location, speciesName, dataName, internalName, firstTimeStep) def _ReadData(self, timeStep): data, = self.openpmd_ts.get_particle( [self.internalName], species=self.speciesName, iteration=timeStep ) self.currentTime = self._ReadTime(timeStep) return data def _ReadTime(self, timeStep): # The line below sets the attribute `_current_i` of openpmd_ts self.openpmd_ts._find_output( None, timeStep ) # This sets the corresponding time self.currentTime = self.openpmd_ts.t[ self.openpmd_ts._current_i ] def _ReadUnits(self): # OpenPMD data always provide conversion to SI units # TODO: Get the units from file self.dataUnits = "arb.u." self.timeUnits = "s" def _OpenFile(self, timeStep): # The line below sets the attribute `_current_i` of openpmd_ts self.openpmd_ts._find_output( None, timeStep ) # This finds the full path to the corresponding file fileName = self.openpmd_ts.h5_files[ self.openpmd_ts._current_i ] file_content = H5File(fileName, 'r') return file_content def _ReadSimulationProperties(self, file_content): # TODO: Add the proper resolution self.grid_resolution = None self.grid_size = None self.grid_units = 'm' def _ReadBasicData(self): file_content = self._OpenFile(self.firstTimeStep) self._ReadSimulationProperties(file_content) file_content.close()
class OpenPMDFieldReader(FieldReaderBase): def __init__(self, location, speciesName, dataName, firstTimeStep): # First check whether openPMD is installed if not openpmd_installed: raise RunTimeError( "You need to install openPMD-viewer, e.g. with:\n" "pip install openPMD-viewer") # Store an openPMD timeseries object # (Its API is used in order to conveniently extract data from the file) self.openpmd_ts = OpenPMDTimeSeries(location, check_all_files=False) self.openpmd_dataName = dataName # Initialize the instance FieldReaderBase.__init__(self, location, speciesName, dataName, firstTimeStep) def _ReadBasicData(self): file_content = self._OpenFile(self.firstTimeStep) self._ReadInternalName(file_content) self._DetermineFieldDimension(file_content) self._GetMatrixShape(file_content) self._ReadSimulationProperties(file_content) file_content.close() def _GetMatrixShape(self, file_content): _, dataset = openpmd_find_dataset(file_content, self.internalName) self.matrixShape = openpmd_get_shape(dataset) def _ReadInternalName(self, file_content): self.internalName = self.openpmd_dataName def _DetermineFieldDimension(self, file_content): # Find the name of the field ; vector fields like E are encoded as "E/x" fieldname = self.internalName.split("/")[0] geometry = self.openpmd_ts.fields_metadata[fieldname]['geometry'] if geometry == '3dcartesian': self.fieldDimension = "3D" elif geometry == '2dcartesian': self.fieldDimension = "2D" else: raise ValueError("Unsupported geometry: %s" % geometry) def _Read1DSlice(self, timeStep, slicePositionX, slicePositionY=None): # Find the name of the field ; vector fields like E are encoded as "E/x" field_and_coord = self.internalName.split("/") if self.fieldDimension == '2D': fieldData, _ = self.openpmd_ts.get_field(*field_and_coord, iteration=timeStep) elementsX = self.matrixShape[-2] selectedRow = round(elementsX * (float(slicePositionX) / 100)) sliceData = np.array(fieldData[selectedRow]) elif self.fieldDimension == '3D': # Slice first along X fieldData = self._Read2DSlice(None, slicePositionX, timeStep) # Then slice along Y elementsY = self.matrixShape[-2] selectedY = round(elementsY * (float(slicePositionY) / 100)) sliceData = np.array(fieldData[selectedY]) return sliceData def _Read2DSlice(self, sliceAxis, slicePosition, timeStep): # Find the name of the field ; vector fields like E are encoded as "E/x" field_and_coord = self.internalName.split("/") # Convert the `slicePosition` from a 0-to-100 number to -1 to 1 slicing = -1. + 2 * slicePosition / 100. # Extract the slice sliceData, _ = self.openpmd_ts.get_field(*field_and_coord, iteration=timeStep, slicing_dir="x", slicing=slicing) return sliceData def _ReadAllFieldData(self, timeStep): # Find the name of the field ; vector fields like E are encoded as "E/x" field_and_coord = self.internalName.split("/") fieldData, _ = self.openpmd_ts.get_field(*field_and_coord, iteration=timeStep, slicing=None) return fieldData def _ReadAxisData(self, timeStep): # Find the name of the field ; vector fields like E are encoded as "E/x" field_and_coord = self.internalName.split("/") # Note: the code below has very bad performance because # it automatically reads the field data, just to extract the metadata # TODO: improve in the future _, field_meta_data = self.openpmd_ts.get_field(*field_and_coord, iteration=timeStep, slicing=None) # Construct the `axisData` from the object `field_meta_data` axisData = {} axisData["x"] = getattr(field_meta_data, "z") axisData["y"] = getattr(field_meta_data, "x") if self.fieldDimension == "3D": axisData["z"] = getattr(field_meta_data, "y") return axisData def _ReadTime(self, timeStep): # The line below sets the attribute `_current_i` of openpmd_ts self.openpmd_ts._find_output(None, timeStep) # This sets the corresponding time self.currentTime = self.openpmd_ts.t[self.openpmd_ts._current_i] def _ReadUnits(self): file_content = self._OpenFile(self.firstTimeStep) # OpenPMD data always provide conversion to SI units self.axisUnits["x"] = "m" self.axisUnits["y"] = "m" self.axisUnits["z"] = "m" self.timeUnits = "t" self.dataUnits = "arb.u." # TODO find the exact unit; needs navigation in file file_content.close() def _ReadSimulationProperties(self, file_content): # TODO: add the proper resolution self.grid_resolution = None self.grid_size = None self.grid_units = "m" def _OpenFile(self, timeStep): # The line below sets the attribute `_current_i` of openpmd_ts self.openpmd_ts._find_output(None, timeStep) # This finds the full path to the corresponding file fileName = self.openpmd_ts.h5_files[self.openpmd_ts._current_i] file_content = H5File(fileName, 'r') return file_content