Skip to content

ResearchItem

ResearchItem

Bases: BaseClassWithFieldData, BaseClassWithFiles, BaseClassWithGroup, BaseClassWithLinking, BaseClassWithNameUpdate, BaseClassWithProtected, BaseClass

Attributes:

Name Type Description
id str

id of the researchitem

name str

name of the researchitem

shortid str

shortid of the researchitem

protected bool

Indicates, if the researchitem is protected in frontend. Does not protect the item for changes made by the api

files List[File]

List of files belonging to this researchitem. See File for more information.

fielddata List[FieldData]

List of field data belonging to this researchitem. See FieldData for more information.

linked_samples List[Sample]

This list contains 'sample' objects linked to the current researchitem. These objects are partially fetched, providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'sample'. Refer to nested objects in Getting Started for further details. For a comprehensive understanding of 'sample' objects, see the provided Sample.

linked_experiments List[Experiment]

This list contains 'experiment' objects linked to the current researchitem. These objects are partially fetched, providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'experiment'. Refer to nested objects in Getting Started for further details. For a comprehensive understanding of 'experiment' objects, see the provided Experiment.

linked_researchitems Dict[str, List[ResearchItem]]

This is a dictionary with category name as keys and lists with the corresponding researchitem objects as values. The researchitem objects are partially fetched, providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'researchitem'. Refer to nested objects in Getting Started for further details. For a comprehensive understanding of 'researchitem' objects, see the provided ResearchItem.

groups List[Group]

This list contains 'group' objects the researchitem belongs to. These objects are partially fetched, providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'group'. Refer to nested objects in Getting Started for further details. For a comprehensive understanding of 'group' objects, see the provided Group.

category Category

Category object of the researchitem.

datatables List[DataTable]

This list contains 'datatable' objects that belong to this researchitem. These objects are partially fetched, providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'datatable'. Refer to nested objects in Getting Started for further details. For a comprehensive understanding of 'datatable' objects, see the provided DataTable.

_fetched bool

This is a Boolean attribute indicating whether all attributes have been retrieved from the server or only the name and ID are present.

Source code in furthrmind\collection\researchitem.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
class ResearchItem(BaseClassWithFieldData, BaseClassWithFiles, BaseClassWithGroup, BaseClassWithLinking,
                   BaseClassWithNameUpdate, BaseClassWithProtected, BaseClass ):
    """
    Attributes
    ----------
    id : str
        id of the researchitem
    name : str
        name of the researchitem
    shortid : str
        shortid of the researchitem
    protected: bool
        Indicates, if the researchitem is protected in frontend. Does not protect the item for changes made by the api
    files : List[File]
        List of files belonging to this researchitem. See [File](file.md) for more information.
    fielddata : List[FieldData]
        List of field data belonging to this researchitem. See [FieldData](fielddata.md) for more information.
    linked_samples : List[Sample]
        This list contains 'sample' objects linked to the current researchitem. These objects are partially fetched,
        providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'sample'.
        Refer to nested objects in [Getting Started](index.md) for further details. For a comprehensive understanding of
        'sample' objects, see the provided [Sample](sample.md).
    linked_experiments : List[Experiment]
        This list contains 'experiment' objects linked to the current researchitem. These objects are partially fetched,
        providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'experiment'.
        Refer to nested objects in [Getting Started](index.md) for further details. For a comprehensive understanding of
        'experiment' objects, see the provided [Experiment](experiment.md).
    linked_researchitems : Dict[str, List[ResearchItem]]
        This is a dictionary with category name as keys and lists with the corresponding `researchitem` objects as values.
        The `researchitem` objects are partially fetched,
        providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'researchitem'.
        Refer to nested objects in [Getting Started](index.md) for further details. For a comprehensive understanding of
        'researchitem' objects, see the provided [ResearchItem](researchitem.md).
    groups : List[Group]
        This list contains 'group' objects the researchitem belongs to. These objects are partially fetched,
        providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'group'.
        Refer to nested objects in [Getting Started](index.md) for further details. For a comprehensive understanding of
        'group' objects, see the provided [Group](group.md).
    category : Category
        [Category](category.md) object of the researchitem.
    datatables : List[DataTable]
        This list contains 'datatable' objects that belong to this researchitem. These objects are partially fetched,
        providing only the name and ID. To retrieve the entire object, invoke the 'get()' method on the 'datatable'.
        Refer to nested objects in [Getting Started](index.md) for further details. For a comprehensive understanding of
        'datatable' objects, see the provided [DataTable](datatable.md).
    _fetched : bool
        This is a Boolean attribute indicating whether all attributes have been retrieved from the server or only
        the name and ID are present.
    """

    id = ""
    name = ""
    neglect = False
    neglect = False
    protected = False
    shortid = ""
    files: List["File"] = []
    fielddata: List["FieldData"] = []
    linked_experiments: List["Experiment"] = []
    linked_samples: List["Sample"] = []
    linked_researchitems: Dict[str, List["ResearchItem"]] = {}
    groups: List["Group"] = []
    category: "Category" = None
    datatables: List["DataTable"] = []

    _attr_definition = {
        "files": {"class": "File"},
        "fielddata": {"class": "FieldData"},
        "groups": {"class": "Group"},
        "linked_samples": {"class": "Sample"},
        "linked_experiments": {"class": "Experiment"},
        "linked_researchitems": {"class": "ResearchItem", "nested_dict": True},
        "datatables": {"class": "DataTable"},
        "category": {"class": "Category"}
    }

    def __init__(self, id=None, data=None):
        super().__init__(id, data)

    def _get_url_instance(self, project_id=None):
        project_url = ResearchItem.fm.get_project_url(project_id)
        url = f"{project_url}/researchitems/{self.id}"
        return url

    @classmethod
    def _get_url_class(cls, id, project_id=None):
        project_url = cls.fm.get_project_url(project_id)
        url = f"{project_url}/researchitems/{id}"
        return url

    @classmethod
    def _get_all_url(cls, project_id=None):
        project_url = cls.fm.get_project_url(project_id)
        url = f"{project_url}/researchitems"
        return url

    @classmethod
    def _post_url(cls, project_id=None):
        project_url = cls.fm.get_project_url(project_id)
        url = f"{project_url}/researchitems"
        return url

    @classmethod
    def get(cls, id: str = "", shortid: str = "", name: str = "", category_name: str = "", category_id: str = "",
            project_id: str = "") -> Self:
        """
        Method to get  one researchitem by its id, short_id or name. If requested by name, also category_name or
        category_id is required.
        If called on an instance of the class, the id of the class is used

        Parameters
        ----------
        id : str, optional
            The id of the requested research item.

        shortid : str, optional
            The short id of the requested research item.

        name : str, optional
            The name of the requested research item.

        category_name : str, optional
            The name of the category the research item belongs to.

        category_id : str, optional
            The id of the category the research item belongs to.

        project_id : str, optional
            Optionally to get a researchitem from another project as the furthrmind sdk was initiated with

        Returns
        -------
        Self
            Instance of the researchitem class.

        Raises
        ------
        AssertionError
            If used as a class method and neither id, shortid, nor name is provided.
            If used as a class method and name is provided but neither category_name nor category_id is provided.

        """

        if isclass(cls):
            assert id or shortid or name, AssertionError("Either id, shortid or name must be given")
            if not id and name:
                assert category_name or category_id, AssertionError("Either category name or id must be given")

        return cls._get(id=id, shortid=shortid, name=name,
                        category_name=category_name, category_id=category_id, project_id=project_id)


    @classmethod
    def get_many(cls, ids: List[str] = (), shortids: List[str] = (), names: List[str] = (),
                 category_name=None, category_id=None, project_id=None) -> List[Self]:
        """
        Method to get many researchitems by ids or shortids. If requested by names, also category_name or category_id
        is required. If requested by name items from one category can be requested at a time.

        Parameters
        ----------
        ids : List[str]
             List of experiment ids.
        shortids : List[str]
             List of experiment short ids.
        names : List[str]
             List of experiment names.
        category_name : str, optional
             Name of the category the research item belongs to.
        category_id : str, optional
             Id of the category the research item belongs to.
        project_id : str, optional
             Optionally to get researchitems from another project as the furthrmind sdk was initiated with

        Returns
        -------
        List[Self]
             List of instances of the researchitem class.

        Raises
        ------
        AssertionError
            ids, shortids, nor names must be provided.
            If names is provided but neither category_name nor category_id is provided.

        """

        assert ids or shortids or names, AssertionError("Either ids, shortids or names must be given")
        if names:
            assert category_name or category_id, AssertionError("Either category_name or category_id must be given")

        return cls._get_many(ids, shortids, names, category_name, category_id, project_id=project_id)

    @classmethod
    def get_all(cls, project_id: str = "") -> List[Self]:
        """
        Method to get all researchitems belonging to one project

        Parameters
        ----------
        project_id: str
            Optionally to get researchitems from another project as the furthrmind sdk was initiated with

        Returns
        -------
        List[Self]
            A list containing instances of the researchitem class.
        """

        return cls._get_all(project_id)


    @classmethod
    @BaseClass._create_instances_decorator(_fetched=False)
    def create(cls, name: str, group_name: str = "", group_id: str = "", category_name: str = "", category_id: str = "",
               project_id=None) -> Self:
        """
        Parameters
        ----------
        name : str
            The name of the item to be created.
        group_name : str, optional
            The name of the group where the new item will belong to. Group name can only be considered for groups that
            are not subgroups. Either `group_name` or `group_id` must be specified.
        group_id : str, optional
            The id of the group where the new item will belong to. Either `group_name` or `group_id` must be specified.
        category_name : str, optional
            The name of the category that the new item will belong to. Either `category_name` or `category_id` must be specified.
        category_id : str, optional
            The id of the category that the new item will belong to. Either `category_name` or `category_id` must be specified.
        project_id : object, optional
            Optionally create a researchitem in another project as the furthrmind sdk was initiated with.

        Returns
        -------
        Self
            instance of the researchitem class

        Raises
        ------
        AssertationError
            If neither group_id nor group_name is provided.
            If neither `category_name` nor `category_id` are specified.

        """

        from furthrmind.collection import Category

        assert group_name or group_id, "Either group_name or group_id must be specified"
        assert category_name or category_id, "Either category name or id must be specified"

        data = cls._prepare_data_for_create(name, group_name, group_id, project_id)

        category_dict = {}
        if category_name:
            category_dict["name"] = category_name
        if category_id:
            category_dict["id"] = category_id

        data["category"] = category_dict
        id = cls._post(data, project_id)

        if "id" not in category_dict:
            categories = Category._get_all(project_id)
            for cat in categories:
                if cat.name == category_name:
                    category_dict["id"] = cat.id
                    break

        data["id"] = id
        return data

    @classmethod
    @BaseClass._create_instances_decorator(_fetched=False)
    def create_many(cls, data_list: List[Dict], project_id: str = "") -> Self:
        """
        Parameters
        ----------
        data_list : List[Dict]
            List of dictionaries containing information about the items to be created. Each dictionary should have the
            following keys:
                - name: str
                    The name of the group to be created.
                - group_name: str
                    The name of the group where the new item will belong to. Group name can only be considered for groups
                    that are not subgroups. Either group_name or group_id must be specified.
                - group_id: int or None
                    The ID of the group where the new item will belong to. Either group_name or group_id must be specified.
                - category_name: str
                    The name of the category that the new item will belong to. Either category_name or category_id must be specified.
                - category_id: int or None
                    The ID of the category that the new item will belong to. Either category_name or category_id must be specified.
        project_id : str, optional
            Optionally to create researchitems in another project as the furthrmind sdk was initiated with

        Returns
        -------
        List[Self]
            A list of instances of the researchitem class created.

        Raises
        ------
        AssertationError
            If name not specified
            If neither category name nor ID is specified.
            If neither group_id nor group_name is provided.


        """

        new_list = []
        category_id_not_present = False

        for data in data_list:
            category_name = data.get('category_name')
            category_id = data.get('category_id')
            assert category_name or category_id, "Either category name or id must be specified"

            # raises an error if name not specified or if neither group_name nor group_id is provided
            temp_data = cls._prepare_data_for_create(data.get("name"), data.get("group_name"), data.get("group_id"),
                                                     project_id)

            category_dict = {}
            if category_name:
                category_dict["name"] = category_name
            if category_id:
                category_dict["id"] = category_id

            temp_data["category"] = category_dict
            new_list.append(temp_data)
            if not "id" in category_dict:
                category_id_not_present = True

        id_list = cls._post(new_list, project_id, force_list=True)
        category_mapping = {}
        if category_id_not_present:
            categories = Category._get_all(project_id)
            category_mapping = {cat.name: cat for cat in categories}

        for data, id in zip(new_list, id_list):
            data["id"] = id
            if "id" not in data["category"]:
                cat_id = category_mapping.get(data["category"]["name"])
                data["category"]["id"] = cat_id

        return new_list

    def add_datatable(self, name: str, columns: List[Dict], project_id: str = "" ) -> "DataTable":
        """
        Method to create a new datatable within this researchitem. Add the created datatable to the datatables attribute

        Parameters
        ----------
        name : str
            Name of the datatable.
        columns : List[Dict]
            A list of columns that should be added to the datatable. Each column is represented as a dictionary with the following keys:
            - name : str
                Name of the column.
            - type : str
                Type of the column. Either "Text" or "Numeric". Data must fit the specified type.
            - data : Union[List[Union[str, float]], pandas.Series]
                List of column values. Data must fit the specified type of the column.
                For Text columns, the items must be convertable to strings
                For Numeric columns, the items must be convertable to floats.
                Can be a list or a pandas.Series.
            - unit : dict or str
                Unit of the column. It can be represented as either a dictionary with 'id' or 'name', or a string
                representing the name or id of the unit.
        project_id : str, optional
            Optionally, specify the id of another project to create the datatable in.

        Returns
        -------
        DataTable
            An instance of the DataTable class representing the created datatable.

        """

        from furthrmind.collection import DataTable
        datatable = DataTable.create(name, researchitem_id=self.id, columns=columns, project_id=project_id)

        new_datatable = list(self.datatables)
        new_datatable.append(datatable)
        self.datatables = new_datatable

        return datatable

add_datatable(name, columns, project_id='')

Method to create a new datatable within this researchitem. Add the created datatable to the datatables attribute

Parameters:

Name Type Description Default
name str

Name of the datatable.

required
columns List[Dict]

A list of columns that should be added to the datatable. Each column is represented as a dictionary with the following keys: - name : str Name of the column. - type : str Type of the column. Either "Text" or "Numeric". Data must fit the specified type. - data : Union[List[Union[str, float]], pandas.Series] List of column values. Data must fit the specified type of the column. For Text columns, the items must be convertable to strings For Numeric columns, the items must be convertable to floats. Can be a list or a pandas.Series. - unit : dict or str Unit of the column. It can be represented as either a dictionary with 'id' or 'name', or a string representing the name or id of the unit.

required
project_id str

Optionally, specify the id of another project to create the datatable in.

''

Returns:

Type Description
DataTable

An instance of the DataTable class representing the created datatable.

Source code in furthrmind\collection\researchitem.py
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
def add_datatable(self, name: str, columns: List[Dict], project_id: str = "" ) -> "DataTable":
    """
    Method to create a new datatable within this researchitem. Add the created datatable to the datatables attribute

    Parameters
    ----------
    name : str
        Name of the datatable.
    columns : List[Dict]
        A list of columns that should be added to the datatable. Each column is represented as a dictionary with the following keys:
        - name : str
            Name of the column.
        - type : str
            Type of the column. Either "Text" or "Numeric". Data must fit the specified type.
        - data : Union[List[Union[str, float]], pandas.Series]
            List of column values. Data must fit the specified type of the column.
            For Text columns, the items must be convertable to strings
            For Numeric columns, the items must be convertable to floats.
            Can be a list or a pandas.Series.
        - unit : dict or str
            Unit of the column. It can be represented as either a dictionary with 'id' or 'name', or a string
            representing the name or id of the unit.
    project_id : str, optional
        Optionally, specify the id of another project to create the datatable in.

    Returns
    -------
    DataTable
        An instance of the DataTable class representing the created datatable.

    """

    from furthrmind.collection import DataTable
    datatable = DataTable.create(name, researchitem_id=self.id, columns=columns, project_id=project_id)

    new_datatable = list(self.datatables)
    new_datatable.append(datatable)
    self.datatables = new_datatable

    return datatable

add_field(field_name='', field_type='', field_id='', value=None, unit=None, position=None)

Method to add a field to the current item

Parameters:

Name Type Description Default
field_name str

Name of field that should be added. If fieldname provided, also fieldtype must be specified. Either fieldname and fieldtype or field_id must be specified.

''
field_type str

Type of field. Must be one of:

  • Numeric fields: numeric, numeric-field, numeric_field
  • Date fields: date, date_field, date-field, datefield
  • Text fields: singleline, singlelinefield, text, text-field, text_field, textfield
  • List fields: combobox, comboboxfield, list, list-field, list_field, listfield
  • Notebook fields: multiline, notebook, notebookfield, notebook-field, notebook_field
  • Checkbox fields: checkbox, checkbox-field, checkbox_field, checkboxfield
  • Calculation fields: calculation, calculation-field, calculation_field, calculationfield
''
field_id str

Id of field that should be added.

''
value Any

Value of the field. The data type of the value depends on the field_type:

  • Numeric fields: float or int, or a string convertible to a float
  • Date fields: datetime, date object, unix timestamp, or string with iso format
  • Text fields: string
  • List fields: dictionary with id or name as key, or string with name, or string with id
  • Notebook fields: dictionary with content as key, or string
  • Checkbox fields: boolean
None
unit Union[Dict, str]

Dictionary with id or name, or string representing the name, or string representing the id.

None
position int

The position where the field should be added in the card. Starting at "0". Optionally.

None

Returns:

Type Description
FieldData

The new FieldData object that was created.

Source code in furthrmind\collection\baseclass.py
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
def add_field(
    self,
    field_name: str = "",
    field_type: str = "",
    field_id: str = "",
    value: Any = None,
    unit: Union[Dict, str] = None,
    position: int = None,
) -> "FieldData":
    """
    Method to add a field to the current item

    Parameters
    ----------
    field_name : str
        Name of field that should be added. If fieldname provided, also fieldtype must be specified.
        Either fieldname and fieldtype or field_id must be specified.
    field_type : str
        Type of field. Must be one of:

        - Numeric fields: numeric, numeric-field, numeric_field
        - Date fields: date, date_field, date-field, datefield
        - Text fields: singleline, singlelinefield, text, text-field, text_field, textfield
        - List fields: combobox, comboboxfield, list, list-field, list_field, listfield
        - Notebook fields: multiline, notebook, notebookfield, notebook-field, notebook_field
        - Checkbox fields: checkbox, checkbox-field, checkbox_field, checkboxfield
        - Calculation fields: calculation, calculation-field, calculation_field, calculationfield
    field_id : str
        Id of field that should be added.
    value : Any
        Value of the field. The data type of the value depends on the field_type:

        - Numeric fields: float or int, or a string convertible to a float
        - Date fields: datetime, date object, unix timestamp, or string with iso format
        - Text fields: string
        - List fields: dictionary with id or name as key, or string with name, or string with id
        - Notebook fields: dictionary with content as key, or string
        - Checkbox fields: boolean

    unit : Union[Dict, str]
        Dictionary with id or name, or string representing the name, or string representing the id.

    position: int
        The position where the field should be added in the card. Starting at "0". Optionally.

    Returns
    -------
    FieldData
        The new FieldData object that was created.

    """

    from .fielddata import FieldData

    if not self._fetched:
        self._get()

    fielddata = FieldData.create(field_name, field_type, field_id, value, unit)

    new_field_data_list = list(self.fielddata)
    if position is not None:
        assert type(position) is int, "Position must be an integer"
        new_field_data_list.insert(position, fielddata)
    else:
        new_field_data_list.append(fielddata)

    self.fielddata = new_field_data_list

    data = {"id": self.id, "fielddata": [{"id": f.id} for f in self.fielddata]}
    self._post(data)
    return fielddata

add_file(file_path='', file_name='', file_id='')

Parameters:

Name Type Description Default
file_path str

File path of the file that should be uploaded.

''
file_name str

Optionally specify the file name if not the original file name should be used.

''
file_id str

ID of the file.

''

Returns:

Type Description
File

The file object that has been added.

Raises:

Type Description
AssertationError

If neither file path nor file_id is specified.

ValueError

If the file path specified does not exist.

Source code in furthrmind\collection\baseclass.py
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
def add_file(
    self, file_path: str = "", file_name: str = "", file_id: str = ""
) -> "File":
    """
    Parameters
    ----------
    file_path : str, optional
        File path of the file that should be uploaded.
    file_name : str, optional
        Optionally specify the file name if not the original file name should be used.
    file_id : str, optional
        ID of the file.

    Returns
    -------
    File
        The file object that has been added.

    Raises
    ------
    AssertationError
        If neither file path nor file_id is specified.
    ValueError
        If the file path specified does not exist.
    """

    from furthrmind.file_loader import FileLoader
    from .file import File

    assert file_path or file_id, "File_path or file_id must be specified"

    if not self._fetched:
        self._get()

    if not file_id:
        assert file_path, "File path must be specified"
        if not os.path.isfile(file_path):
            raise ValueError("File does not exist")

        fl = FileLoader(self.fm.host, self.fm.api_key)
        file_id, file_name = fl.uploadFile(file_path, file_name)
        if not file_name:
            file_path = file_path.replace("\\", "/")
            file_name = os.path.basename(file_path)
        file_data = {"id": file_id, "name": file_name}
    else:
        file_data = {"id": file_id}

    file_list = [{"id": f.id} for f in self.files]
    file_list.append(file_data)
    post_data = {"id": self.id, "files": file_list}

    id = self._post(post_data)
    file = File(data=file_data)
    new_file_list = list(self.files)
    new_file_list.append(file)
    self.files = new_file_list
    return file

add_linked_experiment(experiment_id='', experiment_name='')

This method is used to link an experiment to the current item. If the experiment is already linked to the item, no action is taken.

Parameters:

Name Type Description Default
experiment_id str

The ID of the experiment to link. Either experiment_id or experiment_name must be provided.

''
experiment_name str

The name of the experiment to link. Either experiment_id or experiment_name must be provided.

''

Returns:

Type Description
str

The ID of the item.

Raises:

Type Description
ValueError

If no experiment is found with the given name.

Source code in furthrmind\collection\baseclass.py
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
def add_linked_experiment(self, experiment_id: str = "", experiment_name: str = ""):
    """
    This method is used to link an experiment to the current item. If the experiment is already linked to the item,
    no action is taken.

    Parameters
    ----------
    experiment_id : str, optional
        The ID of the experiment to link. Either `experiment_id` or `experiment_name` must be provided.
    experiment_name : str, optional
        The name of the experiment to link. Either `experiment_id` or `experiment_name` must be provided.

    Returns
    -------
    str
        The ID of the item.

    Raises
    ------
    ValueError
        If no experiment is found with the given name.

    """

    from furthrmind.collection import Experiment

    assert (
        experiment_id or experiment_name
    ), "Either experiment_id or experiment_name must be specified"

    if not self._fetched:
        self._get()

    if experiment_name:
        exp = Experiment.get(name=experiment_name)
        if not exp:
            raise ValueError("No exp found with the given name")
        experiment_id = exp.id
    else:
        exp = Experiment.get(experiment_id)

    experiment_id_list = [item.id for item in self.linked_experiments]
    if experiment_id in experiment_id_list:
        return self.id

    experiment_id_list.append(experiment_id)

    linked_experiment = [{"id": exp_id} for exp_id in experiment_id_list]
    data = {"id": self.id, "experiments": linked_experiment}

    self._post(data=data)
    new_linked_experiments = list(self.linked_experiments)
    new_linked_experiments.append(exp)
    self.linked_experiments = new_linked_experiments
    return self.id

add_linked_researchitem(researchitem_id)

Method is to link a research item to the current item

Parameters:

Name Type Description Default
researchitem_id str

The id of the research item to be linked. If not specified, the method will raise an assertion error.

required

Returns:

Type Description
str

The id of the current research item.

Raises:

Type Description
AssertionError

If researchitem_id is not specified.

Source code in furthrmind\collection\baseclass.py
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
def add_linked_researchitem(self, researchitem_id: str):
    """
    Method is to link a research item to the current item

    Parameters
    ----------
    researchitem_id : str
        The id of the research item to be linked. If not specified, the method will raise an assertion error.

    Returns
    -------
    str
        The id of the current research item.

    Raises
    ------
    AssertionError
        If researchitem_id is not specified.

    """

    from furthrmind.collection import ResearchItem

    assert researchitem_id, "researchitem_id must be specified"

    if not self._fetched:
        self._get()

    researchitem_id_list = []
    for cat in self.linked_researchitems:
        researchitem_id_list.extend(
            [ri_id.id for ri_id in self.linked_researchitems[cat]]
        )

    if researchitem_id in researchitem_id_list:
        return self.id

    researchitem_id_list.append(researchitem_id)

    linked_researchitems = [{"id": ri_id} for ri_id in researchitem_id_list]

    data = {"id": self.id, "researchitems": linked_researchitems}

    self._post(data=data)
    ri = ResearchItem.get(id=researchitem_id)
    research_item_dict = dict(self.linked_researchitems)
    if ri.category.name in self.linked_researchitems:
        new_linked_researchitems = list(self.linked_researchitems[ri.category.name])
    else:
        new_linked_researchitems = []

    new_linked_researchitems.append(ri)
    research_item_dict[ri.category.name] = new_linked_researchitems
    self.linked_researchitems = research_item_dict

    return self.id

add_linked_sample(sample_id='', sample_name='')

Method is to link a sample to the current item

Parameters:

Name Type Description Default
sample_id str

id to the sample you want to link, either id or name must be given

''
sample_name str

name of the sample you want to link, either name or id must be given

''

Returns:

Type Description
str

the id of the item

Raises:

Type Description
ValueError

If no sample found with the given name

Source code in furthrmind\collection\baseclass.py
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
def add_linked_sample(self, sample_id: str = "", sample_name: str = ""):
    """
    Method is to link a sample to the current item

    Parameters
    ----------
    sample_id : str, optional
        id to the sample you want to link, either id or name must be given
    sample_name : str, optional
        name of the sample you want to link, either name or id must be given

    Returns
    -------
    str
        the id of the item

    Raises
    ------
    ValueError
        If no sample found with the given name

    """

    from furthrmind.collection import Sample

    assert (
        sample_id or sample_name
    ), "Either sample_id or sample_name must be specified"

    if not self._fetched:
        self._get()

    if sample_name:
        s = Sample.get(name=sample_name)
        if not s:
            raise ValueError("No sample found with the given name")
        sample_id = s.id
    else:
        s = Sample.get(sample_id)

    sample_id_list = [item.id for item in self.linked_samples]
    if sample_id in sample_id_list:
        return self.id

    sample_id_list.append(sample_id)

    linked_samples = [{"id": s_id} for s_id in sample_id_list]

    data = {"id": self.id, "samples": linked_samples}

    self._post(data=data)
    new_linked_samples = list(self.linked_samples)
    new_linked_samples.append(s)
    self.linked_samples = new_linked_samples
    return self.id

add_many_fields(data_list)

Method to add many fields to the current item

Parameters:

Name Type Description Default
data_list List[Dict]

List of dictionaries containing the information about the fields to be added. Each dictionary should have the following keys:

  • field_name: Name of the field to be added. Either field_name and field_type or field_id must be specified.
  • field_type: Type of the field. Must be one of the following:

    • Numeric fields: numeric, numeric-field, numeric_field
    • Date fields: date, date_field, date-field, datefield
    • Text fields: singleline, singlelinefield, text, text-field, text_field, textfield
    • List fields: combobox, comboboxfield, list, list-field, list_field, listfield
    • Notebook fields: multiline, notebook, notebookfield, notebook-field, notebook_field
    • Checkbox fields: checkbox, checkbox-field, checkbox_field, checkboxfield
    • Calculation fields: calculation, calculation-field, calculation_field, calculationfield
  • field_id: ID of the field to be added.

  • value: Value of the field. The required format depends on the field_type:

    • Numeric: float or int, or a string convertible to a float.
    • Date: datetime, date object, Unix timestamp, or string in ISO format.
    • SingleLine: string.
    • ComboBoxEntry: Dictionary with ID or name as key, or string with name, or string with ID.
    • MultiLine: Dictionary with content as key, or string.
    • CheckBox: Boolean.
  • unit: Dictionary with ID or name as key, or string with name, or string with ID.

  • position: int, The position where the field should be added in the card. Starting at "0". Optionally.
required

Returns:

Type Description
List[FieldData]

List of FieldData objects representing the added fields.

Source code in furthrmind\collection\baseclass.py
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
def add_many_fields(self, data_list: List[Dict]) -> List["FieldData"]:
    """
    Method to add many fields to the current item

    Parameters
    ----------
    data_list: List[Dict]
        List of dictionaries containing the information about the fields to be added. Each dictionary should have the following keys:

        - field_name: Name of the field to be added. Either field_name and field_type or field_id must be specified.
        - field_type:
            Type of the field. Must be one of the following:

            - Numeric fields: numeric, numeric-field, numeric_field
            - Date fields: date, date_field, date-field, datefield
            - Text fields: singleline, singlelinefield, text, text-field, text_field, textfield
            - List fields: combobox, comboboxfield, list, list-field, list_field, listfield
            - Notebook fields: multiline, notebook, notebookfield, notebook-field, notebook_field
            - Checkbox fields: checkbox, checkbox-field, checkbox_field, checkboxfield
            - Calculation fields: calculation, calculation-field, calculation_field, calculationfield

        - field_id: ID of the field to be added.
        - value: Value of the field. The required format depends on the field_type:

            - Numeric: float or int, or a string convertible to a float.
            - Date: datetime, date object, Unix timestamp, or string in ISO format.
            - SingleLine: string.
            - ComboBoxEntry: Dictionary with ID or name as key, or string with name, or string with ID.
            - MultiLine: Dictionary with content as key, or string.
            - CheckBox: Boolean.

        - unit: Dictionary with ID or name as key, or string with name, or string with ID.
        - position: int, The position where the field should be added in the card. Starting at "0". Optionally.

    Returns
    -------
    List["FieldData"]
        List of FieldData objects representing the added fields.

    """

    from .fielddata import FieldData

    if not self._fetched:
        self._get()

    fielddata_list = FieldData.create_many(data_list)

    new_field_data_list = list(self.fielddata)
    for fielddata, data in zip(fielddata_list, data_list):
        if "position" in data:
            assert type(data["position"]) is int, "Position must be an integer"
            new_field_data_list.insert(data["position"], fielddata)
        else:
            new_field_data_list.append(fielddata)

    self.fielddata = new_field_data_list

    data = {"id": self.id, "fielddata": [{"id": f.id} for f in self.fielddata]}
    self._post(data)
    return fielddata_list

copy(item_to_be_copied_id, name, group_id=None, group_name=None, fielddata=True, files=True, datatables=True, project_id=None) classmethod

summary

Parameters:

Name Type Description Default
item_to_be_copied_id str

the id of the item that should be copied

required
name str

the name of the new item

required
group_id str

id of the group, where the new item should be created, Either group_id or group_name must be specified, by default None

None
group_name str

the name of the group, where the new item should be created, Either group_name or group_id must be specified, by default None

None
fielddata bool

whether the fielddata should be copied or not, by default True

True
files bool

whether the files of the item should be copied or not, by default True

True
datatables bool

whether the datatables of the item should be copied or not, by default True

True
project_id str

if the item should be created in another project. If None, the project is used the furthrmind sdk was initiated with, by default None

None

Returns:

Type Description
Self

A new instance of the class

Raises:

Type Description
AssertionError

if name is not set or not a string

AssertionError

if group_id and group_name are not set

Source code in furthrmind\collection\baseclass.py
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
@classmethod
def copy(
    cls,
    item_to_be_copied_id: str,
    name: str,
    group_id: str = None,
    group_name: str = None,
    fielddata: bool = True,
    files: bool = True,
    datatables: bool = True,
    project_id: str = None,
) -> Self:
    """_summary_

    Parameters
    ----------
    item_to_be_copied_id : str, optional
        the id of the item that should be copied
    name : str, optional
        the name of the new item
    group_id : str, optional
        id of the group, where the new item should be created, Either `group_id` or `group_name` must be specified, by default None
    group_name : str, optional
        the name of the group, where the new item should be created, Either group_name or group_id must be specified, by default None
    fielddata : bool, optional
        whether the fielddata should be copied or not, by default True
    files : bool, optional
        whether the files of the item should be copied or not, by default True
    datatables : bool, optional
        whether the datatables of the item should be copied or not, by default True
    project_id : str, optional
        if the item should be created in another project. If None, the project is used the furthrmind sdk was initiated with, by default None

    Returns
    -------
    Self
        A new instance of the class

    Raises
    ------
    AssertionError
        if name is not set or not a string
    AssertionError
        if group_id and group_name are not set
    """

    assert name and isinstance(name, str), "Name must be a string"
    assert group_id or group_name, "Either group_id or group_name must be specified"

    item_to_be_copied = cls.get(item_to_be_copied_id)
    if not item_to_be_copied:
        raise ValueError("Item to be copied not found")

    if not project_id:
        project_id = cls.fm.project_id

    if not group_id and group_name:
        group = cls.fm.Group.get(name=group_name, project_id=project_id)
        group_id = group.id

    data = {
        "targetProject": project_id,
        "targetGroup": group_id,
        "sourceId": item_to_be_copied_id,
        "collection": cls.__name__,
        # includeExps: true,
        # includeSamples: true,
        # includeResearchItems: true,
        # includeSubgroups: true,
        "includeFields": fielddata,
        "includeRawData": datatables,
        "includeFiles": files}

    result = cls._post(data, endpoint="/copy-item")
    new_id = result.get("id")
    new_item = cls.get(new_id)

    update_id = new_item.update_name(name)
    if not update_id == new_id:
        new_item.delete()
        raise ValueError("Error updating the name, most likely name conflict")
    return new_item

create(name, group_name='', group_id='', category_name='', category_id='', project_id=None) classmethod

Parameters:

Name Type Description Default
name str

The name of the item to be created.

required
group_name str

The name of the group where the new item will belong to. Group name can only be considered for groups that are not subgroups. Either group_name or group_id must be specified.

''
group_id str

The id of the group where the new item will belong to. Either group_name or group_id must be specified.

''
category_name str

The name of the category that the new item will belong to. Either category_name or category_id must be specified.

''
category_id str

The id of the category that the new item will belong to. Either category_name or category_id must be specified.

''
project_id object

Optionally create a researchitem in another project as the furthrmind sdk was initiated with.

None

Returns:

Type Description
Self

instance of the researchitem class

Raises:

Type Description
AssertationError

If neither group_id nor group_name is provided. If neither category_name nor category_id are specified.

Source code in furthrmind\collection\researchitem.py
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
@classmethod
@BaseClass._create_instances_decorator(_fetched=False)
def create(cls, name: str, group_name: str = "", group_id: str = "", category_name: str = "", category_id: str = "",
           project_id=None) -> Self:
    """
    Parameters
    ----------
    name : str
        The name of the item to be created.
    group_name : str, optional
        The name of the group where the new item will belong to. Group name can only be considered for groups that
        are not subgroups. Either `group_name` or `group_id` must be specified.
    group_id : str, optional
        The id of the group where the new item will belong to. Either `group_name` or `group_id` must be specified.
    category_name : str, optional
        The name of the category that the new item will belong to. Either `category_name` or `category_id` must be specified.
    category_id : str, optional
        The id of the category that the new item will belong to. Either `category_name` or `category_id` must be specified.
    project_id : object, optional
        Optionally create a researchitem in another project as the furthrmind sdk was initiated with.

    Returns
    -------
    Self
        instance of the researchitem class

    Raises
    ------
    AssertationError
        If neither group_id nor group_name is provided.
        If neither `category_name` nor `category_id` are specified.

    """

    from furthrmind.collection import Category

    assert group_name or group_id, "Either group_name or group_id must be specified"
    assert category_name or category_id, "Either category name or id must be specified"

    data = cls._prepare_data_for_create(name, group_name, group_id, project_id)

    category_dict = {}
    if category_name:
        category_dict["name"] = category_name
    if category_id:
        category_dict["id"] = category_id

    data["category"] = category_dict
    id = cls._post(data, project_id)

    if "id" not in category_dict:
        categories = Category._get_all(project_id)
        for cat in categories:
            if cat.name == category_name:
                category_dict["id"] = cat.id
                break

    data["id"] = id
    return data

create_many(data_list, project_id='') classmethod

Parameters:

Name Type Description Default
data_list List[Dict]

List of dictionaries containing information about the items to be created. Each dictionary should have the following keys: - name: str The name of the group to be created. - group_name: str The name of the group where the new item will belong to. Group name can only be considered for groups that are not subgroups. Either group_name or group_id must be specified. - group_id: int or None The ID of the group where the new item will belong to. Either group_name or group_id must be specified. - category_name: str The name of the category that the new item will belong to. Either category_name or category_id must be specified. - category_id: int or None The ID of the category that the new item will belong to. Either category_name or category_id must be specified.

required
project_id str

Optionally to create researchitems in another project as the furthrmind sdk was initiated with

''

Returns:

Type Description
List[Self]

A list of instances of the researchitem class created.

Raises:

Type Description
AssertationError

If name not specified If neither category name nor ID is specified. If neither group_id nor group_name is provided.

Source code in furthrmind\collection\researchitem.py
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
@classmethod
@BaseClass._create_instances_decorator(_fetched=False)
def create_many(cls, data_list: List[Dict], project_id: str = "") -> Self:
    """
    Parameters
    ----------
    data_list : List[Dict]
        List of dictionaries containing information about the items to be created. Each dictionary should have the
        following keys:
            - name: str
                The name of the group to be created.
            - group_name: str
                The name of the group where the new item will belong to. Group name can only be considered for groups
                that are not subgroups. Either group_name or group_id must be specified.
            - group_id: int or None
                The ID of the group where the new item will belong to. Either group_name or group_id must be specified.
            - category_name: str
                The name of the category that the new item will belong to. Either category_name or category_id must be specified.
            - category_id: int or None
                The ID of the category that the new item will belong to. Either category_name or category_id must be specified.
    project_id : str, optional
        Optionally to create researchitems in another project as the furthrmind sdk was initiated with

    Returns
    -------
    List[Self]
        A list of instances of the researchitem class created.

    Raises
    ------
    AssertationError
        If name not specified
        If neither category name nor ID is specified.
        If neither group_id nor group_name is provided.


    """

    new_list = []
    category_id_not_present = False

    for data in data_list:
        category_name = data.get('category_name')
        category_id = data.get('category_id')
        assert category_name or category_id, "Either category name or id must be specified"

        # raises an error if name not specified or if neither group_name nor group_id is provided
        temp_data = cls._prepare_data_for_create(data.get("name"), data.get("group_name"), data.get("group_id"),
                                                 project_id)

        category_dict = {}
        if category_name:
            category_dict["name"] = category_name
        if category_id:
            category_dict["id"] = category_id

        temp_data["category"] = category_dict
        new_list.append(temp_data)
        if not "id" in category_dict:
            category_id_not_present = True

    id_list = cls._post(new_list, project_id, force_list=True)
    category_mapping = {}
    if category_id_not_present:
        categories = Category._get_all(project_id)
        category_mapping = {cat.name: cat for cat in categories}

    for data, id in zip(new_list, id_list):
        data["id"] = id
        if "id" not in data["category"]:
            cat_id = category_mapping.get(data["category"]["name"])
            data["category"]["id"] = cat_id

    return new_list

delete(id='', project_id='') classmethod

Method to delete an item. Can be called as a classmethod with providing the id to be deleted or on the instance of a class

Parameters:

Name Type Description Default
id str

The id of the resource to delete

''
project_id str

Optionally to delete an item in another project as the furthrmind sdk was initiated with

''

Returns:

Type Description
str

The id of the item

Source code in furthrmind\collection\baseclass.py
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
@classmethod
def delete(cls, id: str = "", project_id: str = "") -> str:
    """
    Method to delete an item. Can be called as a classmethod with providing the id to be deleted or on the instance
    of a class

    Parameters
    ----------
    id : str
        The id of the resource to delete
    project_id : str, optional
        Optionally to delete an item in another project as the furthrmind sdk was initiated with

    Returns
    -------
    str
        The id of the item
    """

    if isclass(cls):
        return cls._delete_class_method(id, project_id)
    else:
        self = cls
        return self._delete_instance_method(project_id)

get(id='', shortid='', name='', category_name='', category_id='', project_id='') classmethod

Method to get one researchitem by its id, short_id or name. If requested by name, also category_name or category_id is required. If called on an instance of the class, the id of the class is used

Parameters:

Name Type Description Default
id str

The id of the requested research item.

''
shortid str

The short id of the requested research item.

''
name str

The name of the requested research item.

''
category_name str

The name of the category the research item belongs to.

''
category_id str

The id of the category the research item belongs to.

''
project_id str

Optionally to get a researchitem from another project as the furthrmind sdk was initiated with

''

Returns:

Type Description
Self

Instance of the researchitem class.

Raises:

Type Description
AssertionError

If used as a class method and neither id, shortid, nor name is provided. If used as a class method and name is provided but neither category_name nor category_id is provided.

Source code in furthrmind\collection\researchitem.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
@classmethod
def get(cls, id: str = "", shortid: str = "", name: str = "", category_name: str = "", category_id: str = "",
        project_id: str = "") -> Self:
    """
    Method to get  one researchitem by its id, short_id or name. If requested by name, also category_name or
    category_id is required.
    If called on an instance of the class, the id of the class is used

    Parameters
    ----------
    id : str, optional
        The id of the requested research item.

    shortid : str, optional
        The short id of the requested research item.

    name : str, optional
        The name of the requested research item.

    category_name : str, optional
        The name of the category the research item belongs to.

    category_id : str, optional
        The id of the category the research item belongs to.

    project_id : str, optional
        Optionally to get a researchitem from another project as the furthrmind sdk was initiated with

    Returns
    -------
    Self
        Instance of the researchitem class.

    Raises
    ------
    AssertionError
        If used as a class method and neither id, shortid, nor name is provided.
        If used as a class method and name is provided but neither category_name nor category_id is provided.

    """

    if isclass(cls):
        assert id or shortid or name, AssertionError("Either id, shortid or name must be given")
        if not id and name:
            assert category_name or category_id, AssertionError("Either category name or id must be given")

    return cls._get(id=id, shortid=shortid, name=name,
                    category_name=category_name, category_id=category_id, project_id=project_id)

get_all(project_id='') classmethod

Method to get all researchitems belonging to one project

Parameters:

Name Type Description Default
project_id str

Optionally to get researchitems from another project as the furthrmind sdk was initiated with

''

Returns:

Type Description
List[Self]

A list containing instances of the researchitem class.

Source code in furthrmind\collection\researchitem.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
@classmethod
def get_all(cls, project_id: str = "") -> List[Self]:
    """
    Method to get all researchitems belonging to one project

    Parameters
    ----------
    project_id: str
        Optionally to get researchitems from another project as the furthrmind sdk was initiated with

    Returns
    -------
    List[Self]
        A list containing instances of the researchitem class.
    """

    return cls._get_all(project_id)

get_many(ids=(), shortids=(), names=(), category_name=None, category_id=None, project_id=None) classmethod

Method to get many researchitems by ids or shortids. If requested by names, also category_name or category_id is required. If requested by name items from one category can be requested at a time.

Parameters:

Name Type Description Default
ids List[str]

List of experiment ids.

()
shortids List[str]

List of experiment short ids.

()
names List[str]

List of experiment names.

()
category_name str

Name of the category the research item belongs to.

None
category_id str

Id of the category the research item belongs to.

None
project_id str

Optionally to get researchitems from another project as the furthrmind sdk was initiated with

None

Returns:

Type Description
List[Self]

List of instances of the researchitem class.

Raises:

Type Description
AssertionError

ids, shortids, nor names must be provided. If names is provided but neither category_name nor category_id is provided.

Source code in furthrmind\collection\researchitem.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
@classmethod
def get_many(cls, ids: List[str] = (), shortids: List[str] = (), names: List[str] = (),
             category_name=None, category_id=None, project_id=None) -> List[Self]:
    """
    Method to get many researchitems by ids or shortids. If requested by names, also category_name or category_id
    is required. If requested by name items from one category can be requested at a time.

    Parameters
    ----------
    ids : List[str]
         List of experiment ids.
    shortids : List[str]
         List of experiment short ids.
    names : List[str]
         List of experiment names.
    category_name : str, optional
         Name of the category the research item belongs to.
    category_id : str, optional
         Id of the category the research item belongs to.
    project_id : str, optional
         Optionally to get researchitems from another project as the furthrmind sdk was initiated with

    Returns
    -------
    List[Self]
         List of instances of the researchitem class.

    Raises
    ------
    AssertionError
        ids, shortids, nor names must be provided.
        If names is provided but neither category_name nor category_id is provided.

    """

    assert ids or shortids or names, AssertionError("Either ids, shortids or names must be given")
    if names:
        assert category_name or category_id, AssertionError("Either category_name or category_id must be given")

    return cls._get_many(ids, shortids, names, category_name, category_id, project_id=project_id)

remove_field(field_name='', field_id='')

Removes a field from the current item.

Parameters:

Name Type Description Default
field_name str

Name of the field that should be removed. Either the field_name or field_id must be specified.

''
field_id str

ID of the field that should be removed.Either the field_name or field_id must be specified.

''

Returns:

Type Description
str

ID of the item after the field is removed.

Raises:

Type Description
ValueError

If no field is found with the given field_name or field_id.

Source code in furthrmind\collection\baseclass.py
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
def remove_field(self, field_name: str = "", field_id: str = ""):
    """
    Removes a field from the current item.

    Parameters
    ----------
    field_name : str, optional
        Name of the field that should be removed. Either the `field_name` or `field_id` must be specified.
    field_id : str, optional
        ID of the field that should be removed.Either the `field_name` or `field_id` must be specified.

    Returns
    -------
    str
        ID of the item after the field is removed.

    Raises
    ------
    ValueError
        If no field is found with the given `field_name` or `field_id`.
    """

    if not self._fetched:
        self._get()

    new_fielddata_list = []
    fielddata_to_be_removed = None
    for fielddata in self.fielddata:
        found = False
        if field_id:
            if fielddata.field_id == field_id:
                fielddata_to_be_removed = fielddata
                found = True
        elif field_name:
            if fielddata.field_name == field_name:
                fielddata_to_be_removed = fielddata
                found = True
        if not found:
            new_fielddata_list.append(fielddata)

    if not fielddata_to_be_removed:
        raise ValueError("No field found with the given fieldid or fieldname")

    self.fielddata = new_fielddata_list
    fielddata_list = [{"id": fd.id} for fd in new_fielddata_list]
    post_data = {"id": self.id, "fielddata": fielddata_list}
    id = self._post(post_data)
    return id

remove_file(file_id='', file_name='')

Method to remove a file from the current item

Parameters:

Name Type Description Default
file_id str

ID of the file that should be removed. Either file_id or file_name must be specified.

''
file_name str

Name of the file to be removed.

''

Returns:

Name Type Description
file_object dict

Object representing the removed file.

Raises:

Type Description
ValueError

If no file is found with the given file_id or file_name.

Source code in furthrmind\collection\baseclass.py
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
def remove_file(self, file_id: str = "", file_name: str = ""):
    """
    Method to remove a file from the current item

    Parameters
    ----------
    file_id: str, optional
        ID of the file that should be removed. Either `file_id` or `file_name` must be specified.
    file_name: str, optional
        Name of the file to be removed.

    Returns
    -------
    file_object: dict
        Object representing the removed file.

    Raises
    ------
    ValueError
        If no file is found with the given `file_id` or `file_name`.

    """

    if not self._fetched:
        self._get()

    new_file_list = []
    file_to_be_removed = None
    for file in self.files:
        found = False
        if file_id:
            if file.id == file_id:
                found = True
                file_to_be_removed = file
        elif file_name:
            if file.name == file_name:
                found = True
                file_to_be_removed = file
        if not found:
            new_file_list.append(file)

    if not file_to_be_removed:
        raise ValueError("No file found with the given file_id or file_name")

    self.files = new_file_list
    file_list = [{"id": f.id} for f in new_file_list]
    post_data = {"id": self.id, "files": file_list}
    id = self._post(post_data)
    return id

remove_linked_experiment(experiment_id='', experiment_name='')

Method to remove a linked experiment from the current item.

Parameters:

Name Type Description Default
experiment_id str

The ID of the experiment you want to unlink. Either experiment_id or experiment_name must be given.

''
experiment_name str

The name of the experiment you want to unlink. Either experiment_id or experiment_name must be given.

''

Returns:

Type Description
str

The ID of the item after removing the linkage.

Raises:

Type Description
ValueError

If no experiment is found with the given name.

AssertionError

If neither experiment_id nor experiment_name is specified.

Source code in furthrmind\collection\baseclass.py
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
def remove_linked_experiment(
    self, experiment_id: str = "", experiment_name: str = ""
):
    """
    Method to remove a linked experiment from the current item.

    Parameters
    ----------
    experiment_id : str, optional
        The ID of the experiment you want to unlink. Either `experiment_id` or `experiment_name` must be given.
    experiment_name : str, optional
        The name of the experiment you want to unlink. Either `experiment_id` or `experiment_name` must be given.

    Returns
    -------
    str
        The ID of the item after removing the linkage.

    Raises
    ------
    ValueError
        If no experiment is found with the given name.
    AssertionError
        If neither `experiment_id` nor `experiment_name` is specified.

    """

    from furthrmind.collection import Experiment

    assert (
        experiment_id or experiment_name
    ), "Either experiment_id or experiment_name must be specified"

    if not self._fetched:
        self._get()

    if experiment_name:
        exp = Experiment.get(name=experiment_name)
        if not exp:
            raise ValueError("No exp found with the given name")
        experiment_id = exp.id

    experiment_id_list = []
    new_linked_items = []
    for item in self.linked_experiments:
        if item.id == experiment_id:
            continue
        new_linked_items.append(item)
        experiment_id_list.append(item.id)

    linked_experiment = [{"id": exp_id} for exp_id in experiment_id_list]
    data = {"id": self.id, "experiments": linked_experiment}

    self._post(data=data)
    self.linked_experiments = new_linked_items
    return self.id

remove_linked_researchitem(researchitem_id)

Method to remove a linked researchitem from the current item

Parameters:

Name Type Description Default
researchitem_id str

The ID of the research item you want to unlink

required

Returns:

Type Description
str

The ID of the item after removing the linkage.

Source code in furthrmind\collection\baseclass.py
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
def remove_linked_researchitem(self, researchitem_id: str):
    """
    Method to remove a linked researchitem from the current item

    Parameters
    ----------
    researchitem_id : str
        The ID of the research item you want to unlink

    Returns
    -------
    str
        The ID of the item after removing the linkage.
    """

    assert researchitem_id, "Either experiment_id must be specified"

    if not self._fetched:
        self._get()

    researchitem_id_list = []
    new_linked_items = {}
    for cat in self.linked_researchitems:
        for item in self.linked_researchitems[cat]:
            if item.id == researchitem_id:
                continue
            if cat not in new_linked_items:
                new_linked_items[cat] = []
            new_linked_items[cat].append(item)
            researchitem_id_list.append(item.id)

    if researchitem_id in researchitem_id_list:
        researchitem_id_list.remove(researchitem_id)

    linked_researchitems = [{"id": ri_id} for ri_id in researchitem_id_list]

    data = {"id": self.id, "researchitems": linked_researchitems}

    self._post(data=data)
    self.linked_researchitems = new_linked_items
    return self.id

remove_linked_sample(sample_id='', sample_name='')

Method is to remove a linked sample from the current item

Parameters:

Name Type Description Default
sample_id str

The id of the sample you want to unlink. Either sample_id or sample_name must be provided.

''
sample_name str

The name of the sample you want to unlink. Either sample_id or sample_name must be provided.

''

Returns:

Type Description
str

The id of the item.

Raises:

Type Description
ValueError

If no sample is found with the given name.

Notes

This method is used to remove a linked sample from the current item. It updates the list of linked samples for the item and saves the changes.

Source code in furthrmind\collection\baseclass.py
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
def remove_linked_sample(self, sample_id: str = "", sample_name: str = ""):
    """
    Method is to remove a linked sample from the current item

    Parameters
    ----------
    sample_id : str, optional
        The id of the sample you want to unlink. Either `sample_id` or `sample_name` must be provided.
    sample_name : str, optional
        The name of the sample you want to unlink. Either `sample_id` or `sample_name` must be provided.

    Returns
    -------
    str
        The id of the item.

    Raises
    ------
    ValueError
        If no sample is found with the given name.

    Notes
    -----
    This method is used to remove a linked sample from the current item. It updates the list of linked samples for the item and saves the changes.

    """

    from furthrmind.collection import Sample

    assert (
        sample_id or sample_name
    ), "Either sample_id or sample_name must be specified"

    if not self._fetched:
        self._get()

    if sample_name:
        s = Sample.get(name=sample_name)
        if not s:
            raise ValueError("No sample found with the given name")
        sample_id = s.id

    sample_id_list = []
    new_linked_items = []
    for item in self.linked_samples:
        if item.id == sample_id:
            continue
        new_linked_items.append(item)
        sample_id_list.append(item.id)

    linked_samples = [{"id": s_id} for s_id in sample_id_list]

    data = {"id": self.id, "samples": linked_samples}
    self._post(data=data)
    self.linked_samples = new_linked_items
    return self.id

set_calculation_result(value, field_name='', field_id='', fielddata_id='')

Method to update a calculation result

Parameters:

Name Type Description Default
value dict

Dictionary containing the calculation result to be set for the field.

required
field_name str

Name of the field that should be updated. Either field_name, field_id, or fielddata_id must be specified.

''
field_id str

ID of the field that should be updated. Either field_name, field_id, or fielddata_id must be specified.

''
fielddata_id str

ID of the fielddata that should be updated. Either field_name, field_id, or fielddata_id must be specified.

''

Returns:

Type Description
id

The ID of the fielddata that was updated.

Raises:

Type Description
ValueError

If no field is found with the given field_id or field_name.

Source code in furthrmind\collection\baseclass.py
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
def set_calculation_result(
    self,
    value: dict,
    field_name: str = "",
    field_id: str = "",
    fielddata_id: str = "",
):
    """
    Method to update a calculation result

    Parameters
    ----------
    value : dict
        Dictionary containing the calculation result to be set for the field.
    field_name : str, optional
        Name of the field that should be updated. Either `field_name`, `field_id`, or `fielddata_id` must be specified.
    field_id : str, optional
        ID of the field that should be updated. Either `field_name`, `field_id`, or `fielddata_id` must be specified.
    fielddata_id : str, optional
        ID of the fielddata that should be updated. Either `field_name`, `field_id`, or `fielddata_id` must be specified.

    Returns
    -------
    id
        The ID of the fielddata that was updated.

    Raises
    ------
    ValueError
        If no field is found with the given `field_id` or `field_name`.
    """

    if not self._fetched:
        self._get()

    fielddata = None
    for item in self.fielddata:
        if fielddata:
            break
        if fielddata_id:
            if item.id == fielddata_id:
                fielddata = item
        if field_id:
            if item.field_id == field_id:
                fielddata = item
        elif field_name:
            if item.field_name.lower() == field_name.lower():
                fielddata = item

    if not fielddata:
        raise ValueError("No field found with the given field_id or field_name")

    return fielddata.set_calculation_result(value)

to_dict()

Converts the object's attributes to a dictionary representation.

Returns:

Type Description
dict

Dictionary containing the object's attributes (excluding private attributes, callable attributes, and attributes of type Furthrmind).

Source code in furthrmind\collection\baseclass.py
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
def to_dict(self):
    """
    Converts the object's attributes to a dictionary representation.

    Returns
    -------
    dict
        Dictionary containing the object's attributes (excluding private attributes, callable attributes, and attributes of type Furthrmind).
    """

    from furthrmind import Furthrmind

    data = {}
    for attr in dir(self):
        if attr.startswith("_"):
            continue
        value = getattr(self, attr)
        if callable(value):
            continue
        if isinstance(value, Furthrmind):
            continue
        data[attr] = self._convert(value)
    return data

update_field_unit(unit, field_name='', field_id='')

Method to update the unit of a field.

Parameters:

Name Type Description Default
unit Union[Dict, str]

Dictionary with id or name, or string representing the name, or string representing the id.

required
field_name str

The name of the field that should be updated. Either field_name or field_id must be specified.

''
field_id str

The ID of the field that should be updated. Either field_name or field_id must be specified.

''

Returns:

Type Description
id

The ID of the updated field.

Raises:

Type Description
ValueError

If no field is found with the given field_id or field_name.

Source code in furthrmind\collection\baseclass.py
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
def update_field_unit(
    self, unit: Union[Dict, str], field_name: str = "", field_id: str = ""
):
    """
    Method to update the unit of a field.

    Parameters
    ----------
    unit : Union[Dict, str]
        Dictionary with id or name, or string representing the name, or string representing the id.
    field_name : str, optional
        The name of the field that should be updated. Either `field_name` or `field_id` must be specified.
    field_id : str, optional
        The ID of the field that should be updated. Either `field_name` or `field_id` must be specified.

    Returns
    -------
    id
        The ID of the updated field.

    Raises
    ------
    ValueError
        If no field is found with the given `field_id` or `field_name`.

    """

    if not self._fetched:
        self._get()

    fielddata = None
    for item in self.fielddata:
        if fielddata is not None:
            break
        if field_id:
            if item.field_id == field_id:
                fielddata = item
        elif field_name:
            if item.field_name.lower() == field_name.lower():
                fielddata = item

    if not fielddata:
        raise ValueError("No field found with the given field_id or field_name")

    return fielddata.update_unit(unit)

update_field_value(value, field_name='', field_id='')

Parameters:

Name Type Description Default
value various data types

The value to be updated in the field.

  • Numeric fields: float or int, or a string convertible to a float
  • Date fields: datetime, date object, unix timestamp, or string with iso format
  • Text fields: string
  • List fields: dictionary with id or name as key, or string with name, or string with id
  • Notebook fields: dictionary with content as key, or string
  • Checkbox fields: boolean
required
field_name str

Name of the field that should be updated. Either field_name or field_id must be specified.

''
field_id str

ID of the field that should be updated. Either field_name or field_id must be specified.

''

Returns:

Type Description
int

The ID of the field that was updated.

Raises:

Type Description
ValueError

If no field is found with the given field_id or field_name.

Source code in furthrmind\collection\baseclass.py
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
def update_field_value(self, value, field_name: str = "", field_id: str = ""):
    """
    Parameters
    ----------
    value : various data types
        The value to be updated in the field.

        - Numeric fields: float or int, or a string convertible to a float
        - Date fields: datetime, date object, unix timestamp, or string with iso format
        - Text fields: string
        - List fields: dictionary with id or name as key, or string with name, or string with id
        - Notebook fields: dictionary with content as key, or string
        - Checkbox fields: boolean
    field_name : str, optional
        Name of the field that should be updated. Either `field_name` or `field_id` must be specified.
    field_id : str, optional
        ID of the field that should be updated. Either `field_name` or `field_id` must be specified.

    Returns
    -------
    int
        The ID of the field that was updated.

    Raises
    ------
    ValueError
        If no field is found with the given `field_id` or `field_name`.
    """

    if not self._fetched:
        self._get()

    fielddata = None
    for item in self.fielddata:
        if fielddata:
            break
        if field_id:
            if item.field_id == field_id:
                fielddata = item
        elif field_name:
            if item.field_name.lower() == field_name.lower():
                fielddata = item

    if not fielddata:
        raise ValueError("No field found with the given field_id or field_name")

    return fielddata.update_value(value)

update_many_names(data_list) classmethod

Method to update the name of many items.

Parameters:

Name Type Description Default
data_list List[Dict[str, str]]

A list of dictionaries representing the data to update the name of many items. Each dictionary should contain the following keys:

- id : str
    The id of the item that should be updated.
- name : str
    The new name of the item.
required

Returns:

Type Description
Self

The updated object.

Source code in furthrmind\collection\baseclass.py
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
@classmethod
def update_many_names(cls, data_list: List[Dict[str, str]]) -> List[str]:
    """
    Method to update the name of many items.

    Parameters
    ----------
    data_list : List[Dict[str, str]]
        A list of dictionaries representing the data to update the name of many items.
        Each dictionary should contain the following keys:

            - id : str
                The id of the item that should be updated.
            - name : str
                The new name of the item.


    Returns
    -------
    Self
        The updated object.
    """

    assert isinstance(data_list, (tuple, list)), "data_list must be a list or tuple"

    new_data_list = []
    for data in data_list:
        assert isinstance(
            data, dict
        ), "Each entry in the data list must be a dictionary"
        assert (
            "name" in data and "id" in data
        ), "Each entry must have a key 'name' and a key 'id'"
        new_data_list.append({"id": data["id"], "name": data["name"]})

    id_list = cls._post(new_data_list, force_list=True)

    return id_list

update_many_protected(data_list) classmethod

With this method the protection state of many items are updated.

Parameters:

Name Type Description Default
data_list List[Dict[str, str]]

A list of dictionaries representing the data for updating the items. Each dictionary should contain the following keys:

- id : str
    The id of the item that should be updated.
- protected : bool
    True or False, whether the item should be protected or not.
required

Returns:

Type Description
Self

The updated object.

Source code in furthrmind\collection\baseclass.py
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
@classmethod
def update_many_protected(cls, data_list: List[Dict[str, str]]) -> List[str]:
    """
    With this method the protection state of many items are updated.

    Parameters
    ----------
    data_list : List[Dict[str, str]]
        A list of dictionaries representing the data for updating the items.
        Each dictionary should contain the following keys:

            - id : str
                The id of the item that should be updated.
            - protected : bool
                True or False, whether the item should be protected or not.


    Returns
    -------
    Self
        The updated object.
    """

    assert isinstance(data_list, (tuple, list)), "data_list must be a list or tuple"

    new_data_list = []
    for data in data_list:
        assert isinstance(
            data, dict
        ), "Each entry in the data list must be a dictionary"
        assert (
            "protected" in data and "id" in data
        ), "Each entry must have a key 'name' and a key 'id'"
        assert isinstance(data["protected"], bool), "protected must be a boolean"
        new_data_list.append({"id": data["id"], "protected": data["protected"]})

    id_list = cls._post(new_data_list, force_list=True)

    return id_list

update_name(name)

The method updates the name of the current item.

Parameters:

Name Type Description Default
name str

New name

required

Returns:

Type Description
str

The id of the item.

Source code in furthrmind\collection\baseclass.py
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
def update_name(self, name: str) -> str:
    """
    The method updates the name of the current item.

    Parameters
    ----------
    name : str
        New name


    Returns
    -------
    str
        The id of the item.
    """

    data = {"id": self.id, "name": name}
    id = self._post(data)
    self.name = name
    return id

update_protected(protected)

This method updates the protection state of the current item.

Parameters:

Name Type Description Default
protected bool

True or False, whether the item should be protected or not.

required

Returns:

Type Description
str

The id of the item.

Source code in furthrmind\collection\baseclass.py
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
def update_protected(self, protected: bool) -> str:
    """
    This method updates the protection state of the current item.

    Parameters
    ----------
    protected : bool
        True or False, whether the item should be protected or not.

    Returns
    -------
    str
        The id of the item.
    """
    if not self._fetched:
        self._get()

    assert isinstance(protected, bool), "protected must be a boolean"

    if self.protected == protected:
        return self.id

    data = {"id": self.id, "protected": protected}
    id = self._post(data)
    self.protected = protected
    return id