Skip to content

Client(endpoint, token)

Creates a new MedConB client.

Parameters:

Name Type Description Default
endpoint str

URL of the MedConB API. E.g. https://api.medconb.example.com/graphql/

required
token str

Authorization token.

required
Source code in medconb_client.py
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
def __init__(
    self,
    endpoint: str,
    token: str,
):
    """
    Creates a new MedConB client.

    Args:
        endpoint (str): URL of the MedConB API. E.g. https://api.medconb.example.com/graphql/
        token (str): Authorization token.
    """
    self.endpoint = endpoint
    self.token = token
    self.transport = RequestsHTTPTransport(
        url=self.endpoint,
        headers={"Authorization": f"Bearer {self.token}"},
        retries=3,
    )
    self.client = GQLClient(
        transport=self.transport,
        fetch_schema_from_transport=True,
        execute_timeout=30,
    )

get_codelist(codelist_id, with_description=False)

Retrieves the codelist by ID from the API and parses the data into the python data structures.

It mirrors the logic of the export and current understanding of transient codesets: Transient codesets are the current version and should be used if they exist. (At some point the API might change to reflect that default behaviour better as it might be a bit confusing atm.)

Source code in medconb_client.py
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
def get_codelist(
    self, codelist_id: str, with_description: bool = False
) -> "Codelist":
    """
    Retrieves the codelist by ID from the API and parses
    the data into the python data structures.

    It mirrors the logic of the export and current understanding
    of transient codesets:
    Transient codesets are the current version and should be used
    if they exist. (At some point the API might change to reflect
    that default behaviour better as it might be a bit confusing
    atm.)
    """
    query = gql(
        _GQL_QUERY_CODELST
        if with_description
        else _GQL_QUERY_CODELST_NO_DESCRIPTION
    )

    with self.client as session:
        result = session.execute(query, variable_values={"codelistID": codelist_id})
        codelist_data = result["codelist"]

        css = codelist_data["codesets"]
        tcss = codelist_data["transientCodesets"]
        codesets: Codesets = Codesets()

        if tcss is None:
            tcss = css

        for cs in tcss:
            codesets.append(
                Codeset(
                    ontology=cs["ontology"]["name"],
                    codes=[
                        (
                            c["code"],
                            c["description"] if with_description else "",
                        )
                        for c in cs["codes"]
                    ],
                )
            )

        return Codelist(
            id=codelist_data["id"],
            name=codelist_data["name"],
            description=codelist_data.get("description"),
            codesets=codesets,
        )

get_codelist_by_name(*, codelist_name, codelist_collection_name=None, phenotype_collection_name=None, phenotype_name=None)

get_codelist_by_name(
    *, codelist_name: str, codelist_collection_name: str
)
get_codelist_by_name(
    *,
    codelist_name: str,
    phenotype_collection_name: str,
    phenotype_name: str
)

Retrieves a Codelist by its name.

Use the arguments codelist_name with either:

  • codelist_collection_name or
  • phenotype_collection_name and phenotype_name

Parameters:

Name Type Description Default
codelist_name str

Name of the codelist

required
codelist_collection_name str

Name of the codelist collection

None
phenotype_collection_name str

Name of the phenotype collection

None
phenotype_name str

Name of the phenotype

None
Source code in medconb_client.py
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
def get_codelist_by_name(
    self,
    *,
    codelist_name,
    codelist_collection_name=None,
    phenotype_collection_name=None,
    phenotype_name=None,
):
    """
    Retrieves a Codelist by its name.

    Use the arguments `codelist_name` with either:

    - `codelist_collection_name` or
    - `phenotype_collection_name` and `phenotype_name`

    Args:
        codelist_name (str): Name of the codelist
        codelist_collection_name (str, optional): Name of the codelist collection
        phenotype_collection_name (str, optional): Name of the phenotype collection
        phenotype_name (str, optional): Name of the phenotype
    """
    # codelist_collection_name = kwargs.get("codelist_collection_name")
    # codelist_name = kwargs.get("codelist_name")
    # phenotype_collection_name = kwargs.get("phenotype_collection_name")
    # phenotype_name = kwargs.get("phenotype_name")

    if codelist_name is None:
        raise ValueError("Invalid arguments: codelist_name is required")

    mode = None

    if codelist_collection_name is not None:
        mode = "collection"
    elif phenotype_collection_name is not None and phenotype_name is not None:
        mode = "phenotype"
    else:
        raise ValueError(
            "Invalid arguments: Specify either codelist_collection_name or"
            " phenotype_collection_name and phenotype_name"
        )

    candidates = self._search_codelist(codelist_name)
    matches = []

    if mode == "collection":
        matches = self._filter_codelist_in_collection(
            candidates, codelist_collection_name
        )
    else:
        matches = self._filter_codelist_in_phenotype(
            candidates, phenotype_collection_name, phenotype_name
        )

    if len(matches) > 1:
        raise ValueError(
            "The codelist can not be retrieved because the name is ambiguous"
        )

    if len(matches) == 0:
        raise ValueError(
            "The codelist can not be retrieved because it was not found"
        )

    return self.get_codelist(matches[0])

get_workspace()

Retrieves a listing of all collections and their codelists/pheontypes within the workspace.

Returns:

Name Type Description
Workspace Workspace

Workspace object containing id and name of all codelists and phenotypes.

Example

For a detailed example, see Examples.

>>> workspace = client.get_workspace()
>>> print(workspace)
Workspace(
    collections=[
        Collection(
            id="ff755b3a-8f93-43a2-bb8f-2ee435e28938",
            name="ATTR CM Library",
            description="...",
            referenceID="...",
            itemType="Codelist",
            items=[
                CodelistInfo(id="...", name="..."),
                CodelistInfo(id="...", name="..."),
                ...
            ],
            ownerID="...",
            locked=False,
            visibility="Private",
        ),
        ...
    ],
    shared=[
        Collection(...),
    ],
)

Source code in medconb_client.py
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
def get_workspace(self) -> Workspace:
    """
    Retrieves a listing of all collections and their codelists/pheontypes
    within the workspace.

    Returns:
        Workspace: Workspace object containing id and name of all codelists and phenotypes.

    Example:
        For a detailed example, see [Examples](/examples#list-all-collections-in-your-workspace).
        ```ipython
        >>> workspace = client.get_workspace()
        >>> print(workspace)
        Workspace(
            collections=[
                Collection(
                    id="ff755b3a-8f93-43a2-bb8f-2ee435e28938",
                    name="ATTR CM Library",
                    description="...",
                    referenceID="...",
                    itemType="Codelist",
                    items=[
                        CodelistInfo(id="...", name="..."),
                        CodelistInfo(id="...", name="..."),
                        ...
                    ],
                    ownerID="...",
                    locked=False,
                    visibility="Private",
                ),
                ...
            ],
            shared=[
                Collection(...),
            ],
        )
        ```
    """
    query = gql(_GQL_QUERY_WORKSPACE)

    with self.client as session:
        result = session.execute(query)
        workspace_data = result["self"]["workspace"]
        return Workspace(**workspace_data)

Codelist(id, name, description, codesets) dataclass

Codelist is a codelist as defined in MedConB.

Attributes:

Name Type Description
id str

ID of the codelist.

name str

Name of the codelist.

description str

Description of the codelist.

codesets Codesets

List of codesets in the codelist.

to_pandas()

Convert the codelists codesets to a pandas DataFrame.

Returns:

Type Description

pd.DataFrame: The codesets as a DataFrame.

Source code in medconb_client.py
57
58
59
60
61
62
63
64
def to_pandas(self):
    """
    Convert the codelists codesets to a pandas DataFrame.

    Returns:
        pd.DataFrame: The codesets as a DataFrame.
    """
    return self.codesets.to_pandas()

Codeset(ontology, codes) dataclass

Codeset is a codeset as defined in MedConB.

Attributes:

Name Type Description
ontology str

Ontology which the codes belong to

codes list[tuple[str, str]]

List of codes, each represented as a tuple of code and description

Codesets

Bases: UserList['Codeset']

Codesets is a list of codesets as defined in MedConB.

It's just a thin wrapper, so we can offer to_pandas.

to_pandas()

Convert the codesets to a pandas DataFrame.

Returns:

Type Description

pd.DataFrame: The codesets as a DataFrame.

Source code in medconb_client.py
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
def to_pandas(self):
    """
    Convert the codesets to a pandas DataFrame.

    Returns:
        pd.DataFrame: The codesets as a DataFrame.
    """
    rows = []
    for codeset in self.data:
        for code, description in codeset.codes:
            rows.append(
                {
                    "ontology": codeset.ontology,
                    "code": code,
                    "description": description,
                }
            )

    return pd.DataFrame(rows)