From 68bded568b66d71555ba075d3a1dc24d743b29d5 Mon Sep 17 00:00:00 2001 From: Gao Date: Wed, 5 Jul 2023 15:16:56 +0200 Subject: [PATCH] regular backup --- Analyser/ImagingAnalyser.py | 97 ++++++++++++++++++++++++ DataContainer/MongoDB.py | 146 +++++++++++++++++++++++++++++++++++- 2 files changed, 242 insertions(+), 1 deletion(-) diff --git a/Analyser/ImagingAnalyser.py b/Analyser/ImagingAnalyser.py index 6445c7c..068918a 100644 --- a/Analyser/ImagingAnalyser.py +++ b/Analyser/ImagingAnalyser.py @@ -4,8 +4,12 @@ import copy class ImageAnalyser(): + """A class for operate with and analyse images + """ def __init__(self) -> None: + """Initialize the class + """ self._image_name = { 'atoms': 'atoms', 'background': 'background', @@ -18,37 +22,101 @@ class ImageAnalyser(): @property def image_name(self): + """The getter of the names of three standard images for absorption images + + :return: The names of three standard images for absorption images + :rtype: dict + """ return self._image_name @image_name.setter def image_name(self, value): + """The setter of the names of three standard images for absorption images. + It has to be a dict and have the follow format: + { + 'atoms': the name of the image with atoms, + 'background': the name of the image without atoms, + 'dark': the name of the image without light, + 'OD': the name of the calculated OD, + } + + :param value: The names of three standard images for absorption images. + :type value: dict + """ self._image_name.update(value) @property def center(self): + """The getter of the center of region of insterest (ROI) + + :return: The center of region of insterest (ROI) + :rtype: tuple + """ return self._center @center.setter def center(self, value): + """The setter of the center of region of insterest (ROI) + + :param value: The center of region of insterest (ROI) + :type value: tuple + """ self._center = value @property def span(self): + """The getter of the span of region of insterest (ROI) + + :return: The span of region of insterest (ROI) + :rtype: tuple + """ return self._span @span.setter def span(self, value): + """The setter of the span of region of insterest (ROI) + + :param value: The span of region of insterest (ROI) + :type value: tuple + """ self._span = value @property def fraction(self): + """The getter of the fraction used to remove the background in the region of insterest (ROI) + + :return: The fraction used to remove the background + :rtype: tuple + """ return self._fraction @fraction.setter def fraction(self, value): + """The setter of the fraction used to remove the background in the region of insterest (ROI) + + :param value: The fraction used to remove the background + :type value: tuple + """ self._fraction = value def get_offset_from_corner(self, dataArray, x_fraction=None, y_fraction=None, fraction=None, xAxisName='x', yAxisName='y'): + """Calculate the background value based on the four coners of the image. + + :param dataArray: The image + :type dataArray: xarray DataArray + :param x_fraction: The fraction of the pixels used x in axis, defaults to None + :type x_fraction: float, optional + :param y_fraction: The fraction of the pixels used y in axis, defaults to None + :type y_fraction: float, optional + :param fraction: The fraction of the pixels used to calculate the background, defaults to None + :type fraction: tuple, optional + :param xAxisName: The name of the x axis in dataArray, defaults to 'x' + :type xAxisName: str, optional + :param yAxisName: The name of the y axis in dataArray, defaults to 'y' + :type yAxisName: str, optional + :return: The value of the background + :rtype: float + """ if fraction is None: if x_fraction is None: @@ -71,11 +139,29 @@ class ImageAnalyser(): return mean / 4 def substract_offset(self, dataArray, **kwargs): + """Remove the backgournd + + :param dataArray: The image + :type dataArray: xarray DataArray + :return: The image after removing background + :rtype: xarray DataArray + """ res = dataArray - self.get_offset_from_corner(dataArray, **kwargs) res.attrs = copy.copy(dataArray.attrs) return res def crop_image(self, dataSet, center=None, span=None): + """Crop the image according to the region of interest (ROI). + + :param dataSet: The images + :type dataSet: xarray DataArray or DataSet + :param center: The center of region of insterest (ROI), defaults to None + :type center: tuple, optional + :param span: the span of region of insterest (ROI), defaults to None + :type span: tuple, optional + :return: The croped images + :rtype: xarray DataArray or DataSet + """ if center is None: center = self._center @@ -110,6 +196,17 @@ class ImageAnalyser(): return dataSet.isel(x=slice(x_start, x_end), y=slice(y_start, y_end)) def get_OD(self, imageAtom, imageBackground, imageDrak): + """_summary_ + + :param imageAtom: _description_ + :type imageAtom: _type_ + :param imageBackground: _description_ + :type imageBackground: _type_ + :param imageDrak: _description_ + :type imageDrak: _type_ + :return: _description_ + :rtype: _type_ + """ numerator = np.atleast_1d(imageBackground - imageDrak) denominator = np.atleast_1d(imageAtom - imageDrak) diff --git a/DataContainer/MongoDB.py b/DataContainer/MongoDB.py index 05af6a7..ce1df0f 100644 --- a/DataContainer/MongoDB.py +++ b/DataContainer/MongoDB.py @@ -16,8 +16,19 @@ npArrayType = type(np.array([0])) class MongoDB: + """A class for communicate with our MongoDB. + """ def __init__(self, mongoClient, mongoDB, date=None) -> None: + """Initialize the class with given handle to our MongoDB client and database. + + :param mongoClient: The handle to MongoDB client + :type mongoClient: pymongo MongoDB client or other MongoDB client + :param mongoDB: The handle to MongoDB database + :type mongoDB: pymongo MongoDB database or other MongoDB database + :param date: The date of data ('YYYY/MM/DD'), can be setted later, defaults to None + :type date: str, optional + """ self.mongoClient = mongoClient self.mongoDB = mongoDB self.xdb = xarray_mongodb.XarrayMongoDB(mongoDB) @@ -27,6 +38,13 @@ class MongoDB: self.set_date(date) def _convert_numpy_type(self, data): + """Convert from numpy type to normal python type. + + :param data: The data need to be converted + :type data: numpy data type + :return: The converted data + :rtype: normal python data type + """ for key in data: typeKey = type(data[key]) if typeKey in npTypeDict: @@ -41,6 +59,15 @@ class MongoDB: return data def _break_dataSet(self, dataSet, scanAxis=None): + """Stack the scan axes of data + + :param dataSet: The xarray DataSet or DataArray stored the data + :type dataSet: xarray DataSet or DataArray + :param scanAxis: a list of the name of scan axes, defaults to None + :type scanAxis: list or array like, optional + :return: The stacked xarray DataSet or DataArray stored the data + :rtype: xarray DataSet or DataArray + """ if scanAxis is None: scanAxis = dataSet.attrs['scanAxis'] @@ -52,12 +79,26 @@ class MongoDB: return stackedDataArray def set_date(self, date): + """Set the date of data + + :param date: The date of data ('YYYY/MM/DD') + :type date: str + """ date = date.split("/") self.year = int(date[0]) self.month = int(date[1]) self.day = int(date[2]) def create_global(self, shotNum, dataSet=None, date=None): + """Creat a the global document in MongoDB + + :param shotNum: The shot number + :type shotNum: str + :param dataSet: The xarray DataSet stored the global parameters, defaults to None + :type dataSet: xarray DataSet, optional + :param date: the date of the data, defaults to None + :type date: str, optional + """ if not date is None: self.set_date(date) @@ -133,6 +174,15 @@ class MongoDB: self.mongoDB['global'].insert_one(data) def _add_data_normal(self, shotNum, runNum, data): + """Write the data directly to the global document + + :param shotNum: The shot number + :type shotNum: str + :param runNum: The run number + :type runNum: int + :param data: The data to be written + :type data: normal python data type + """ if runNum is None: runNum = 0 @@ -148,6 +198,17 @@ class MongoDB: self.mongoDB['global'].update_one(filter, {"$set": data}, upsert=False) def _add_data_xarray_dataArray(self, shotNum, dataArray, name=None, scanAxis=None): + """Write the data in a type of xarray DataArray to the MongoDb. + + :param shotNum: The shot number + :type shotNum: str + :param dataArray: The xarray DataArray to be written + :type dataArray: xarray DataArray + :param name: The name of the DataArray, defaults to None + :type name: str, optional + :param scanAxis: The scan axes of the data, defaults to None + :type scanAxis: array like, optional + """ if scanAxis is None: scanAxis = list(dataArray.coords) @@ -190,6 +251,17 @@ class MongoDB: self.mongoDB['global'].update_one(filter, {"$set": data_label}, upsert=False) def _add_data_xarray_dataSet(self, shotNum, dataSet, name, scanAxis=None): + """Write the data in a type of xarray DataSet to the MongoDb. + + :param shotNum: The shot number + :type shotNum: str + :param dataSet: The xarray DataSet to be written + :type dataSet: xarray DataSet + :param name: The name of the DataArray, defaults to None + :type name: str, optional + :param scanAxis: The scan axes of the data, defaults to None + :type scanAxis: array like, optional + """ if scanAxis is None: scanAxis = list(dataSet.coords) @@ -235,6 +307,17 @@ class MongoDB: self.mongoDB['global'].update_one(filter, {"$set": data_label}, upsert=False) def _add_data_additional(self, shotNum, runNum, data, name): + """Write the data in an additional document + + :param shotNum: The shot number + :type shotNum: str + :param runNum: The run number + :type runNum: int + :param data: The data to be written + :type data: normal python data type + :param name: The name of the data + :type name: str + """ if runNum is None: runNum = 0 @@ -262,6 +345,21 @@ class MongoDB: self.mongoDB['global'].update_one(filter, {"$set": data_label}, upsert=False) def add_data(self, shotNum, data, runNum=None, date=None, name=None, engine='normal'): + """Write a new data to MongoDB + + :param shotNum: The shot number + :type shotNum: str + :param data: The data needs to be written + :type data: standard python data type, numpy type, xarray DataArray or xarray DataSet + :param runNum: The run number, defaults to None + :type runNum: int, optional + :param date: The date of the data ('YYYY/MM/DD'), defaults to None + :type date: str, optional + :param name: The name of the data, defaults to None + :type name: str, optional + :param engine: The engine for different types of the data, defaults to 'normal' + :type engine: str, optional + """ if not date is None: self.set_date(date) @@ -276,6 +374,17 @@ class MongoDB: self._add_data_additional(shotNum=shotNum, runNum=runNum, data=data, name=name) def read_global_single(self, shotNum, runNum, date=None): + """Read the global document of specified shot and run from MongoDB. + + :param shotNum: The shot number + :type shotNum: str + :param runNum: The run number + :type runNum: int + :param date: The date of the data ('YYYY/MM/DD'), defaults to None + :type date: str, optional + :return: The global document + :rtype: dict + """ if not date is None: self.set_date(date) @@ -291,6 +400,15 @@ class MongoDB: return self.mongoDB['global'].find_one(filter) def read_global_all(self, shotNum, date=None): + """Read the global document of all runs in the specified shot from MongoDB, and extract the scan axes. + + :param shotNum: The shot number + :type shotNum: str + :param date: The date of the data ('YYYY/MM/DD'), defaults to None + :type date: str, optional + :return: The global document + :rtype: dict + """ from xarray.core.utils import equivalent @@ -379,13 +497,38 @@ class MongoDB: return result def _load_data_single(self, mongoID, engine): + """load the document according to given _ID + + :param mongoID: the ID of document in MongoDB + :type mongoID: MongoDB ID object + :param engine: _description_ + :type engine: _type_ + :return: The engine for different types of the data + :rtype: str + """ + if engine == 'xarray': return self.xdb.get(mongoID) if engine == 'additional': return self.mongoDB.additional.find_one({'_id': mongoID}) def load_data_single(self, shotNum=None, runNum=None, globalDict=None, date=None, field=None): - + """go through the given global document and find all the MongoDB object, then replace them with the document they linked to. + + :param shotNum: The shot number, defaults to None + :type shotNum: str, optional + :param runNum: The run number, defaults to None + :type runNum: int, optional + :param globalDict: The given global document, defaults to None + :type globalDict: dict, optional + :param date: The date of the data ('YYYY/MM/DD'), defaults to None + :type date: str, optional + :param field: If not None, the function will only go through these keys, defaults to None + :type field: array like, optional + :return: The document with loaded data + :rtype: dict + """ + if not date is None: self.set_date(date) @@ -411,4 +554,5 @@ class MongoDB: return res def load_data(self, shotNum=None, globalDict=None, date=None, field=None): + # load all the data of specified shot pass \ No newline at end of file