---
title: PFS
description: A configuration file format used in MIKE software
code-annotations: hover
---

A PFS file is a text file with a tree structure that contains parameters and settings for MIKE tools and engines. MIKE IO can read, modify and create PFS files. 

## The PFS file

The content of the PFS file is similar to a nested dictionary. The root element is often called the *target*. Some PFS files have multiple root elements. The below sections are called *PFS Sections* which can be nested and contain key-value pairs called *keywords* and *parameters*. 

```ini
[TARGET1]                                  # <1>
   keywordA = parameterA                   # <1>    
   [SECTION1]                              # <1>
      keywordB = parameterB                # <1>
      keywordC = parameterC                # <1>
      [SECTION2]                           # <1>
         keywordD = parameterD             # <1>
      EndSect  // SECTION2                 # <1>
   EndSect  // SECTION1                    # <1>
EndSect  // TARGET1                        # <1>

[TARGET2]                                  # <2>
   keywordE = parameterE                   # <2>
   [SECTION3]                              # <2>
      keywordF = parameterF                # <2>
   EndSect  // SECTION3                    # <2>
EndSect  // TARGET2                        # <2>
```

1. First target, access this part with `pfs.targets[0]`
2. Second target, access this part with `pfs.targets[1]`

::: {.callout-note}
**Comments** `//` is used to add comments to the PFS file (e.g. `// SECTION2`), the comments are ignored by MIKE IO.
:::

## Read

When a PFS file is read with MIKE IO, a `PfsDocument` object is created. It will contain one or more `PfsSection` objects - one for each target. The PfsSections will typically contain other PfsSections together with a number of key-value pairs. 

A PFS file is read using [](`mikeio.read_pfs`):

```{python}
import mikeio

pfs = mikeio.read_pfs("../data/pfs/concat.mzt")
pfs
```

### PfsDocument

The [](`mikeio.PfsDocument`) is the MIKE IO equivalent to a PFS file. Its targets can be accessed by their name (as properties), like this:  

```{python}
pfs.txconc
```

Or by the `pfs.targets` object (which is a list of PfsSections). Each of the targets is a `PfsSection` object consisting of key-value pairs (keyword-parameter) and other PfsSections. 

The [](`mikeio.PfsDocument`) object is similar to a dictionary. You can loop over its contents with `items()`, `keys()` and `values()` like a dictionary. 


### PfsSection

The [](`mikeio.PfsSection`) object is also similar to a dictionary. You can loop over its contents with `items()`, `keys()` and `values()` like a dictionary. 

```{python}
pfs.txconc.keys()
```

You can access a specific parameter with the `get()` method: 

```{python}
pfs.txconc.get("CLSID")
```

Or as a property with dot-notation---which is prefered in most cases as it is more readable: 

```{python}
pfs.txconc.CLSID
```

A PfsSection can be converted to a dictionary with the to_dict() method: 

```{python}
pfs.txconc.Setup.File_1.to_dict()
```

If a PfsSection contains enumerated subsections, they can be converted to a pandas DataFrame with the `to_dataframe()` method: 

```{python}
pfs.txconc.Setup.to_dataframe(prefix="File_")
```



### Unique or non-unique keywords

Depending on the engine intended for reading the PFS file it may or may not make sense to have multiple identical keywords in the same PfsSection. MIKE 21/3 and the marine tools does *not* support non-unique keywords---if non-unique keywords are present, only the first will be read and the presence is most likely a mistake made by hand-editing the file. In other tools, e.g. MIKE Plot Composer, non-unique keywords are used a lot. How MIKE IO shall deal with non-unique keywords can be specified using the `unique_keywords` argument in the [](`mikeio.read_pfs`) function: 

```python
pfs = mikeio.read_pfs("myplot.plt", unique_keywords=False)
```

If a PfsSection contains non-unique PfsSections or keywords and `unique_keywords=False`, the repeated key will only appear once and the corresponding value will be a list. 


## Update

The PfsSection object can be modified. Existing values can be changed, new key-value pairs can be added, subsections can added or removed. 



### Modify existing keyword

It is very simple to modify an existing keyword: 

```python
pfs.txconc.Setup.Name = "new name"
```


### Add new key-value pair

A new key-value pair can be added, like in a dictionary, in this way: 

```python
pfs.txconc.Setup["NewKeyword"] = 12.0
```


### Add new section as a copy of another section

Often a PfsSection is added using an existing PfsSection as a template. 

```python
s = pfs.txconc.Setup.File_1.copy()
s.InputFile = '|.\tide3.dfs1|'
pfs.txconc.Setup["File_3"] = s
```



### Add new section from a dictionary

A PfsSection can be created from a dictionary and then added to another PfsSection like any other key-value pair: 

```{python}
d = {'InputFile': '|.\\tide4.dfs1|', 'Items': 1}
s = mikeio.PfsSection(d)
pfs.txconc.Setup["File_4"] = s
```


## Write to file

A Pfs document can be written to a file using the `write` method. 

```python
pfs.write("new.pfs")
```


## Create new Pfs files

A new PFS file can be created from dictionary in the following way: 

```{python}

d = dict(
    key1=1,
    lst=[0.3, 0.7],
    file_name=r"|path\file.dfs0|",
    start_time=[2019, 7, 1, 0, 0, 0],
)
pfs = mikeio.PfsDocument({"MYTOOL": d})
pfs
```

Multiple targets can be achieved by providing list of dictionaries, in this way you can create a PFS file with multiple targets for the same tool. 

```{python}
t1 = {"file_name": r"|path\file1.dfs0|"}
t2 = {"file_name": r"|path\file2.dfs0|"}

pfs = mikeio.PfsDocument([t1, t2], names=["ATOOL", "ATOOL"])
pfs
```


