Repository: neurostuff/nimare
Issue: Raise warning if coordinates dataset contains both positive and negative z_stats

## Summary
<!--What is the nature of the bug?-->
Seems weird to perform a meta-analysis with peaks being reported at both the positive and negative thresholds

## Additional details
<!--Please fill in the following details-->
- NiMARE version: 0.0.7 dev

### What were you trying to do?

Thinking about how users may use the output of #446 

### What did you expect to happen?

Raise warning/error when both positive/negative values are detected in z_stat column?

### What actually happened?

The dataset will run on any estimator

## Reproducing the bug
<!--Please share any steps you performed that revealed the bug-->
<!--Please include any code snippets.
Enclose them in triple back-ticks (```)
Like this:

```
<code>
```
-->


Changed files:
nimare/transforms.py, nimare/dataset.py, nimare/tests/test_dataset.py

diff --git a/nimare/dataset.py b/nimare/dataset.py
index 2d605df..262a028 100755
--- a/nimare/dataset.py
+++ b/nimare/dataset.py
@@ -4,6 +4,7 @@ import inspect
 import json
 import logging
 import os.path as op
+import warnings
 
 import numpy as np
 import pandas as pd
@@ -103,6 +104,22 @@ class Dataset(NiMAREBase):
         self.texts = _dict_to_df(id_df, data, key="text")
         self.basepath = None
 
+        if "z_stat" in self.coordinates.columns:
+            # "z_stat" column may contain Nones
+            if not self.coordinates["z_stat"].isna().any():
+                # Ensure z_stat is treated as float
+                self.coordinates["z_stat"] = self.coordinates["z_stat"].astype(float)
+
+                # Raise warning if coordinates dataset contains both positive and negative z_stats
+                if ((self.coordinates["z_stat"].values >= 0).any()) and (
+                    (self.coordinates["z_stat"].values < 0).any()
+                ):
+                    warnings.warn(
+                        "Coordinates dataset contains both positive and negative z_stats. "
+                        "The algorithms currently implemented in NiMARE are designed for "
+                        "one-sided tests. This might lead to unexpected results."
+                    )
+
     def __repr__(self):
         """Show basic Dataset representation.
 
diff --git a/nimare/tests/test_dataset.py b/nimare/tests/test_dataset.py
index 65bc262..3f70076 100644
--- a/nimare/tests/test_dataset.py
+++ b/nimare/tests/test_dataset.py
@@ -1,5 +1,8 @@
 """Test nimare.dataset (Dataset IO/transformations)."""
+import copy
+import json
 import os.path as op
+import warnings
 
 import nibabel as nib
 import numpy as np
@@ -51,3 +54,45 @@ def test_empty_dset():
     # dictionary with no information
     minimal_dict = {"study-0": {"contrasts": {"1": {}}}}
     dataset.Dataset(minimal_dict)
+
+
+def test_posneg_warning():
+    """Smoke test for nimare.dataset.Dataset initialization with positive and negative z_stat."""
+    db_file = op.join(get_test_data_path(), "neurosynth_dset.json")
+    with open(db_file, "r") as f_obj:
+        data = json.load(f_obj)
+
+    data_pos_zstats = copy.deepcopy(data)
+    data_neg_zstats = copy.deepcopy(data)
+    for pid in data.keys():
+        for expid in data[pid]["contrasts"].keys():
+            exp = data[pid]["contrasts"][expid]
+
+            if "coords" not in exp.keys():
+                continue
+
+            if "z_stat" not in exp["coords"].keys():
+                continue
+
+            n_zstats = len(exp["coords"]["z_stat"])
+            rand_arr = np.random.randn(n_zstats)
+            rand_pos_arr = np.abs(rand_arr)
+            rand_neg_arr = np.abs(rand_arr) * -1
+
+            data[pid]["contrasts"][expid]["coords"]["z_stat"] = rand_arr.tolist()
+            data_neg_zstats[pid]["contrasts"][expid]["coords"]["z_stat"] = rand_neg_arr.tolist()
+            data_pos_zstats[pid]["contrasts"][expid]["coords"]["z_stat"] = rand_pos_arr.tolist()
+
+    # Test Warning is raised if there are positive and negative z-stat
+    with pytest.warns(UserWarning, match=r"positive and negative z_stats"):
+        dset_posneg = dataset.Dataset(data)
+
+    # Test Warning is not raised if there are only positive or negative z-stat
+    with warnings.catch_warnings():
+        warnings.simplefilter("error")
+        dset_pos = dataset.Dataset(data_pos_zstats)
+        dset_neg = dataset.Dataset(data_neg_zstats)
+
+    assert isinstance(dset_posneg, nimare.dataset.Dataset)
+    assert isinstance(dset_pos, nimare.dataset.Dataset)
+    assert isinstance(dset_neg, nimare.dataset.Dataset)
diff --git a/nimare/transforms.py b/nimare/transforms.py
index ea8eea3..952f690 100644
--- a/nimare/transforms.py
+++ b/nimare/transforms.py
@@ -3,6 +3,7 @@
 import copy
 import logging
 import os.path as op
+import warnings
 
 import nibabel as nib
 import numpy as np
@@ -456,10 +457,20 @@ class ImagesToCoordinates(NiMAREBase):
             original_ids = set(old_coordinates_df["id"])
             metadata.loc[metadata["id"].isin(original_ids), "coordinate_source"] = "original"
 
-        # ensure z_stat is treated as float
         if "z_stat" in coordinates_df.columns:
+            # ensure z_stat is treated as float
             coordinates_df["z_stat"] = coordinates_df["z_stat"].astype(float)
 
+            # Raise warning if coordinates dataset contains both positive and negative z_stats
+            if ((coordinates_df["z_stat"].values >= 0).any()) and (
+                (coordinates_df["z_stat"].values < 0).any()
+            ):
+                warnings.warn(
+                    "Coordinates dataset contains both positive and negative z_stats. "
+                    "The algorithms currently implemented in NiMARE are designed for "
+                    "one-sided tests. This might lead to unexpected results."
+                )
+
         new_dataset = copy.deepcopy(dataset)
         new_dataset.coordinates = coordinates_df
         new_dataset.metadata = metadata